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

Kon*_*hin 18 comparison objective-c 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...
Run Code Online (Sandbox Code Playgroud)

bbu*_*bum 26

扩展Laurent的答案.

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

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

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

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

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


n8g*_*ray 13

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

只是为了好玩,这是证明.假设我们可以创建一个函数来判断两个块是否相等,称为EQ(b1,b2).现在我们将使用该功能来解决暂停问题.我们创建了一个新函数HALT(M,I),它告诉我们图灵机M是否会在输入上停止我喜欢这样:

BOOL HALT(M,I) {
  return EQ(
    ^(int) {return 0;},
    ^(int) {M(I); return 0;}
  );
}
Run Code Online (Sandbox Code Playgroud)

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

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