假设您在 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
~~~~~~~~ ^ ~~~~~~~~
考虑之后,我确定这不起作用的原因是因为您无法确定闭包是否真的相等。闭包不仅仅是代码,还包括创建它的上下文,包括任何捕获。您无法检查相等性的原因是没有有意义的方式使两个闭包相等。
要了解为什么捕获很重要,请查看以下代码。
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
显然这些闭包是相等的。不可能实现任何适用于所有情况的合理的平等定义,因此 Apple 甚至没有尝试过。这比在某些情况下提供错误的不完整实现更安全。
关于swift - 在 Swift 3 中,比较两个闭包的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45270371/