How do you test functions and closures for equality?

Solution 1:

Chris Lattner wrote on the developer forums:

This is a feature we intentionally do not want to support. There are a variety of things that will cause pointer equality of functions (in the swift type system sense, which includes several kinds of closures) to fail or change depending on optimization. If "===" were defined on functions, the compiler would not be allowed to merge identical method bodies, share thunks, and perform certain capture optimizations in closures. Further, equality of this sort would be extremely surprising in some generics contexts, where you can get reabstraction thunks that adjust the actual signature of a function to the one the function type expects.

https://devforums.apple.com/message/1035180#1035180

This means that you should not even try to compare closures for equality because optimizations may affect the outcome.

Solution 2:

I searched a lot. There seems to be no way of function pointer comparison. The best solution I got is to encapsulate the function or closure in an hashable object. Like:

var handler:Handler = Handler(callback: { (message:String) in
            //handler body
}))

Solution 3:

Simplest way is designate the block type as @objc_block, and now you can cast it to an AnyObject which is comparable with ===. Example:

    typealias Ftype = @convention(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

Update 2021; changed @objc_block to @convention(block) to support Swift 2.x and later (which don't recognize @objc_block).