18
float pi = 3.14;
float (^piSquare)(void) = ^(void){ return pi * pi; };
float (^piSquare2)(void) = ^(void){ return pi * pi; };

[piSquare isEqualTo: piSquare2]; // -> want it to behave like -isEqualToString...
4

3 回答 3

26

扩展Laurent的答案。

块是实现和数据的组合。为了使两个块相等,它们需要具有完全相同的实现并捕获完全相同的数据。因此,比较需要比较实现和数据。

有人可能会认为比较实现很容易。这实际上不是因为编译器的优化器的工作方式。

虽然比较简单数据相当简单,但块可以捕获对象——包括 C++ 对象(可能有一天会真正起作用)——并且比较可能需要也可能不需要考虑这一点。一个简单的实现会简单地对捕获的内容进行字节级别的比较。然而,人们可能还希望使用对象级比较器来测试对象的相等性。

然后是 __block 变量的问题。块本身实际上没有任何与 __block 捕获的变量相关的元数据,因为它不需要它来满足所述变量的要求。因此,比较无法在不显着更改编译器代码生成的情况下比较 __block 值。

所有这一切都是说,不,目前无法比较块并概述其中的一些原因。如果您觉得这很有用,请通过http://bugreport.apple.com/提交错误并提供用例。

于 2010-01-30T18:44:14.717 回答
13

撇开编译器实现和语言设计的问题不谈,您所要求的显然是无法确定的(除非您只关心检测 100% 相同的程序)。判断两个程序是否计算相同的函数相当于解决停机问题。这是赖斯定理的一个经典结论:图灵机的任何“有趣”属性都是不可判定的,其中“有趣”只是意味着它对某些机器是正确的,而对其他机器是错误的。

只是为了好玩,这是证据。假设我们可以创建一个函数来确定两个块是否等价,称为 EQ(b1, b2)。现在我们将使用该函数来解决停机问题。我们创建了一个新函数 HALT(M, I),它告诉我们图灵机 M 是否会在我喜​​欢的输入时停止:

BOOL HALT(M,I) {
  return EQ(
    ^(int) {return 0;},
    ^(int) {M(I); return 0;}
  );
}

如果 M(I) 停止,则块是等效的,因此 HALT(M,I) 返回 YES。如果 M(I) 没有停止,则块等价,因此 HALT(M,I) 返回 NO。请注意,我们不必执行这些块——我们假设的 EQ 函数可以通过查看它们来计算它们的等价性。

我们现在已经解决了停机问题,我们知道这是不可能的。因此,情商不可能存在。

于 2010-02-01T00:22:05.883 回答
4

我不认为这是可能的。块可以粗略地视为高级函数(可以访问全局或局部变量)。就像你不能比较函数的内容一样,你也不能比较块的内容。

您所能做的就是比较它们的低级实现,但我怀疑编译器会保证两个具有相同内容的块共享它们的实现。

于 2010-01-30T15:08:12.000 回答