假设您在
Swift 3中有两个类型(Int) – >()的闭包,并测试它们是否彼此相同:
typealias Baz = (Int)->() let closure1:Baz = { print("foo \($0)") } let closure2:Baz = { print("bar \($0)") } if(closure1 == closure2) { print("equal") }
这无法编译,给出消息:
Binary operator ‘==’ cannot be applied to two ‘(Int)->()’ operands
好吧,那么,我们如何比较两个相同类型的闭包,看看它们是否相同?
解决方法
我很确定无法确定两个闭包是否相等.
显然,逻辑等式检查是不可能的.这相当于找到了停止问题的答案. (只是测试你的代码是否等同于一段永远循环的代码.如果是,它不会停止.如果不是,它会停止.)
从理论上讲,您可能希望===运算符测试两个闭包是否完全相同,但是当我在Playground中尝试它时会出错.
Playground execution Failed: error: MyPlayground.playground:1:20: error: cannot check reference equality of functions; operands here have types '(Int) -> ()' and '(Int) -> ()' let bar = closure1 === closure2 ~~~~~~~~ ^ ~~~~~~~~
考虑过这个问题后,我确定无法解决问题的原因是因为你无法确定闭包是否真的相同.闭包不仅仅是代码,还包括创建它的上下文,包括任何捕获.你无法检查相等性的原因是没有任何有意义的方法可以使两个闭包相等.
要了解为什么thew捕获很重要,请查看以下代码.
func giveMeClosure(aString: String) -> () -> String { return { "returning " + aString } } let closure1 = giveMeClosure(aString: "foo") let closure2 = giveMeClosure(aString: "bar")
closure1和closure2是否相等?它们都使用相同的代码块
print(closure1()) // prints "returning foo" print(closure2()) // prints "returning bar"
所以他们不平等.您可以争辩说,您可以检查代码是否相同且捕获是否相同,但是怎么样
func giveMeACount(aString: String) -> () -> Int { return { aString.characters.count } } let closure3 = giveMeACount(aString: "foo") let closure4 = giveMeACount(aString: "bar") print(closure3()) // prints 3 print(closure4()) // prints 3
显然这些封闭是平等的.实现任何合理的平等定义都不可能在每种情况下都有效,因此苹果公司甚至没有尝试过.这比提供在某些情况下错误的不完整实现更安全.