Jes*_*ssy 83 closures equality swift
书中说"功能和闭包是参考类型".那么,你怎么知道引用是否相等?==和===不起作用.
func a() { }
let å = a
let b = å === å // Could not find an overload for === that accepts the supplied arguments
Run Code Online (Sandbox Code Playgroud)
以下是Catterwauls如何处理这个问题:
dre*_*wag 65
Chris Lattner在开发者论坛上写道:
这是我们有意不想支持的功能.有许多事情会导致函数的指针相等(在swift类型系统意义上,包括几种闭包)失败或根据优化而改变.如果在函数上定义了"===",则不允许编译器合并相同的方法体,共享thunk,并在闭包中执行某些捕获优化.此外,在某些泛型上下文中,这种相等性是非常令人惊讶的,在这些上下文中,您可以获得将函数的实际签名调整为函数类型所期望的重新抽取thunk.
https://devforums.apple.com/message/1035180#1035180
这意味着您甚至不应该尝试比较闭包是否相等,因为优化可能会影响结果.
最简单的方法是将块类型指定为@objc_block,现在可以将其转换为与之相当的AnyObject ===.例:
typealias Ftype = @objc_block (s:String) -> ()
let f : Ftype = {
ss in
println(ss)
}
let ff : Ftype = {
sss in
println(sss)
}
let obj1 = unsafeBitCast(f, AnyObject.self)
let obj2 = unsafeBitCast(ff, AnyObject.self)
let obj3 = unsafeBitCast(f, AnyObject.self)
println(obj1 === obj2) // false
println(obj1 === obj3) // true
Run Code Online (Sandbox Code Playgroud)
小智 7
我搜索了很多.似乎没有办法比较函数指针.我得到的最好的解决方案是将函数或闭包封装在一个可散列的对象中.喜欢:
var handler:Handler = Handler(callback: { (message:String) in
//handler body
}))
Run Code Online (Sandbox Code Playgroud)
我一直在寻找答案.我终于找到了它.
您需要的是实际的函数指针及其隐藏在函数对象中的上下文.
func peekFunc<A,R>(f:A->R)->(fp:Int, ctx:Int) {
typealias IntInt = (Int, Int)
let (hi, lo) = unsafeBitCast(f, IntInt.self)
let offset = sizeof(Int) == 8 ? 16 : 12
let ptr = UnsafePointer<Int>(lo+offset)
return (ptr.memory, ptr.successor().memory)
}
@infix func === <A,R>(lhs:A->R,rhs:A->R)->Bool {
let (tl, tr) = (peekFunc(lhs), peekFunc(rhs))
return tl.0 == tr.0 && tl.1 == tr.1
}
Run Code Online (Sandbox Code Playgroud)
这是演示:
// simple functions
func genericId<T>(t:T)->T { return t }
func incr(i:Int)->Int { return i + 1 }
var f:Int->Int = genericId
var g = f; println("(f === g) == \(f === g)")
f = genericId; println("(f === g) == \(f === g)")
f = g; println("(f === g) == \(f === g)")
// closures
func mkcounter()->()->Int {
var count = 0;
return { count++ }
}
var c0 = mkcounter()
var c1 = mkcounter()
var c2 = c0
println("peekFunc(c0) == \(peekFunc(c0))")
println("peekFunc(c1) == \(peekFunc(c1))")
println("peekFunc(c2) == \(peekFunc(c2))")
println("(c0() == c1()) == \(c0() == c1())") // true : both are called once
println("(c0() == c2()) == \(c0() == c2())") // false: because c0() means c2()
println("(c0 === c1) == \(c0 === c1)")
println("(c0 === c2) == \(c0 === c2)")
Run Code Online (Sandbox Code Playgroud)
请参阅以下网址,了解原因及工作原理:
如您所见,它只能检查身份(第二次测试结果false).但这应该足够好了.
已经两天了,还没有人提出解决方案,所以我将我的评论更改为答案:
\n\n据我所知,您无法检查函数(如您的示例)和元类(例如,MyClass.self)的相等性或同一性:
但是 \xe2\x80\x93 这只是一个想法 \xe2\x80\x93 我不禁注意到where泛型中的子句似乎能够检查类型的相等性。那么也许您可以利用它,至少可以检查身份?