是否可以按内容比较两个Objective-C块?

时间:2010-01-30 13:04:26

标签: objective-c comparison objective-c-blocks

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...

3 个答案:

答案 0 :(得分:26)

扩展劳伦特的答案。

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

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

虽然比较简单数据非常简单,但是块可以捕获对象 - 包括C ++对象(实际上可能在某一天工作) - 并且比较可能需要也可能不需要考虑。一个简单的实现只是对捕获的内容进行字节级比较。但是,人们可能还希望使用对象级别比较器来测试对象的相等性。

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

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

答案 1 :(得分:13)

抛开编译器实现和语言设计的问题,你要求的是可证明不可判断的(除非你只关心检测100%相同的程序)。确定两个程序是否计算相同的函数等同于解决暂停问题。这是赖斯定理的经典结果:图灵机的任何“有趣”属性都是不可判定的,其中“有趣”只意味着某些机器是真的,而其他机器则是假的。

只是为了好玩,这是证明。假设我们可以创建一个函数来判断两个块是否相等,称为EQ(b1,b2)。现在我们将使用该功能来解决暂停问题。我们创建了一个新函数HALT(M,I),它告诉我们Turing机器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函数可以通过查看它们来计算它们的等价。

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

答案 2 :(得分:4)

我不认为这是可能的。可以将块粗略地视为高级函数(可以访问全局变量或局部变量)。与无法比较函数内容的方法相同,您无法比较块的内容。

您所能做的就是比较他们的low-level implementation,但我怀疑编译器会保证两个具有相同内容的块共享其实现。