How do you test functions and closures for equality?












79















The book says that "functions and closures are reference types". So, how do you find out if the references are equal? == and === don't work.



func a() { }
let å = a
let b = å === å // Could not find an overload for === that accepts the supplied arguments


Here is how the Catterwauls are dealing with this:



MultiClosures & Equatable Closures



tests










share|improve this question




















  • 5





    As far as I can tell, you also can't check equality of metaclasses (e.g., MyClass.self)

    – Jiaaro
    Jun 9 '14 at 0:55











  • It shouldn't be necessary to compare two closures for identity. Can you give an example of where you would do this? There might be an alternative solution.

    – Bill
    Jun 9 '14 at 12:08






  • 1





    Multicast closures, a la C#. They're necessarily uglier in Swift, because you can't overload the (T, U) "operator", but we can still create them ourselves. Without being able to remove closures from an invocation list by reference, however, we need to create our own wrapper class. That is a drag, and shouldn't be necessary.

    – Jessy
    Jun 9 '14 at 15:42








  • 2





    Great question, but totally separate thing: your use of a diacritic on å to reference a is really interesting. Is there a convention you're exploring here? (I don't know if I actually like it or not; but it seems like it could be very powerful, especially in pure functional programming.)

    – Rob Napier
    Jun 11 '14 at 12:50






  • 2





    @Bill I am storing closures in an Array and can't use indexOf({$0 == closure} in order to find and remove them. Now I have to restructure my code due to optimization which I believe to be poor language design.

    – Zack Morris
    Jan 20 '16 at 22:50
















79















The book says that "functions and closures are reference types". So, how do you find out if the references are equal? == and === don't work.



func a() { }
let å = a
let b = å === å // Could not find an overload for === that accepts the supplied arguments


Here is how the Catterwauls are dealing with this:



MultiClosures & Equatable Closures



tests










share|improve this question




















  • 5





    As far as I can tell, you also can't check equality of metaclasses (e.g., MyClass.self)

    – Jiaaro
    Jun 9 '14 at 0:55











  • It shouldn't be necessary to compare two closures for identity. Can you give an example of where you would do this? There might be an alternative solution.

    – Bill
    Jun 9 '14 at 12:08






  • 1





    Multicast closures, a la C#. They're necessarily uglier in Swift, because you can't overload the (T, U) "operator", but we can still create them ourselves. Without being able to remove closures from an invocation list by reference, however, we need to create our own wrapper class. That is a drag, and shouldn't be necessary.

    – Jessy
    Jun 9 '14 at 15:42








  • 2





    Great question, but totally separate thing: your use of a diacritic on å to reference a is really interesting. Is there a convention you're exploring here? (I don't know if I actually like it or not; but it seems like it could be very powerful, especially in pure functional programming.)

    – Rob Napier
    Jun 11 '14 at 12:50






  • 2





    @Bill I am storing closures in an Array and can't use indexOf({$0 == closure} in order to find and remove them. Now I have to restructure my code due to optimization which I believe to be poor language design.

    – Zack Morris
    Jan 20 '16 at 22:50














79












79








79


23






The book says that "functions and closures are reference types". So, how do you find out if the references are equal? == and === don't work.



func a() { }
let å = a
let b = å === å // Could not find an overload for === that accepts the supplied arguments


Here is how the Catterwauls are dealing with this:



MultiClosures & Equatable Closures



tests










share|improve this question
















The book says that "functions and closures are reference types". So, how do you find out if the references are equal? == and === don't work.



func a() { }
let å = a
let b = å === å // Could not find an overload for === that accepts the supplied arguments


Here is how the Catterwauls are dealing with this:



MultiClosures & Equatable Closures



tests







closures swift equality






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 21 '16 at 16:19







Jessy

















asked Jun 8 '14 at 23:38









JessyJessy

3,64612027




3,64612027








  • 5





    As far as I can tell, you also can't check equality of metaclasses (e.g., MyClass.self)

    – Jiaaro
    Jun 9 '14 at 0:55











  • It shouldn't be necessary to compare two closures for identity. Can you give an example of where you would do this? There might be an alternative solution.

    – Bill
    Jun 9 '14 at 12:08






  • 1





    Multicast closures, a la C#. They're necessarily uglier in Swift, because you can't overload the (T, U) "operator", but we can still create them ourselves. Without being able to remove closures from an invocation list by reference, however, we need to create our own wrapper class. That is a drag, and shouldn't be necessary.

    – Jessy
    Jun 9 '14 at 15:42








  • 2





    Great question, but totally separate thing: your use of a diacritic on å to reference a is really interesting. Is there a convention you're exploring here? (I don't know if I actually like it or not; but it seems like it could be very powerful, especially in pure functional programming.)

    – Rob Napier
    Jun 11 '14 at 12:50






  • 2





    @Bill I am storing closures in an Array and can't use indexOf({$0 == closure} in order to find and remove them. Now I have to restructure my code due to optimization which I believe to be poor language design.

    – Zack Morris
    Jan 20 '16 at 22:50














  • 5





    As far as I can tell, you also can't check equality of metaclasses (e.g., MyClass.self)

    – Jiaaro
    Jun 9 '14 at 0:55











  • It shouldn't be necessary to compare two closures for identity. Can you give an example of where you would do this? There might be an alternative solution.

    – Bill
    Jun 9 '14 at 12:08






  • 1





    Multicast closures, a la C#. They're necessarily uglier in Swift, because you can't overload the (T, U) "operator", but we can still create them ourselves. Without being able to remove closures from an invocation list by reference, however, we need to create our own wrapper class. That is a drag, and shouldn't be necessary.

    – Jessy
    Jun 9 '14 at 15:42








  • 2





    Great question, but totally separate thing: your use of a diacritic on å to reference a is really interesting. Is there a convention you're exploring here? (I don't know if I actually like it or not; but it seems like it could be very powerful, especially in pure functional programming.)

    – Rob Napier
    Jun 11 '14 at 12:50






  • 2





    @Bill I am storing closures in an Array and can't use indexOf({$0 == closure} in order to find and remove them. Now I have to restructure my code due to optimization which I believe to be poor language design.

    – Zack Morris
    Jan 20 '16 at 22:50








5




5





As far as I can tell, you also can't check equality of metaclasses (e.g., MyClass.self)

– Jiaaro
Jun 9 '14 at 0:55





As far as I can tell, you also can't check equality of metaclasses (e.g., MyClass.self)

– Jiaaro
Jun 9 '14 at 0:55













It shouldn't be necessary to compare two closures for identity. Can you give an example of where you would do this? There might be an alternative solution.

– Bill
Jun 9 '14 at 12:08





It shouldn't be necessary to compare two closures for identity. Can you give an example of where you would do this? There might be an alternative solution.

– Bill
Jun 9 '14 at 12:08




1




1





Multicast closures, a la C#. They're necessarily uglier in Swift, because you can't overload the (T, U) "operator", but we can still create them ourselves. Without being able to remove closures from an invocation list by reference, however, we need to create our own wrapper class. That is a drag, and shouldn't be necessary.

– Jessy
Jun 9 '14 at 15:42







Multicast closures, a la C#. They're necessarily uglier in Swift, because you can't overload the (T, U) "operator", but we can still create them ourselves. Without being able to remove closures from an invocation list by reference, however, we need to create our own wrapper class. That is a drag, and shouldn't be necessary.

– Jessy
Jun 9 '14 at 15:42






2




2





Great question, but totally separate thing: your use of a diacritic on å to reference a is really interesting. Is there a convention you're exploring here? (I don't know if I actually like it or not; but it seems like it could be very powerful, especially in pure functional programming.)

– Rob Napier
Jun 11 '14 at 12:50





Great question, but totally separate thing: your use of a diacritic on å to reference a is really interesting. Is there a convention you're exploring here? (I don't know if I actually like it or not; but it seems like it could be very powerful, especially in pure functional programming.)

– Rob Napier
Jun 11 '14 at 12:50




2




2





@Bill I am storing closures in an Array and can't use indexOf({$0 == closure} in order to find and remove them. Now I have to restructure my code due to optimization which I believe to be poor language design.

– Zack Morris
Jan 20 '16 at 22:50





@Bill I am storing closures in an Array and can't use indexOf({$0 == closure} in order to find and remove them. Now I have to restructure my code due to optimization which I believe to be poor language design.

– Zack Morris
Jan 20 '16 at 22:50












8 Answers
8






active

oldest

votes


















60














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.






share|improve this answer



















  • 17





    This just bit me, which was kind of devastating because I had been storing closures in an Array and now can't remove them with indexOf({$0 == closure} so I have to refactor. IMHO optimization shouldn't influence language design, so without a quick fix like the now deprecated @objc_block in matt's answer, I would argue that Swift can't properly store and retrieve closures at this time. So I don't think it's appropriate to advocate the use of Swift in callback heavy code like the kind encountered in web development. Which was the whole reason we switched to Swift in the first place...

    – Zack Morris
    Jan 20 '16 at 23:12






  • 3





    @ZackMorris Store some sort of identifier with the closure so you can remove it later. If you are using reference types you can just store a reference to the object otherwise you can come up with your own identifier system. You could even design a type that has a closure and a unique identifier that you can use instead of a plain closure.

    – drewag
    Jan 21 '16 at 5:36








  • 4





    @drewag Yeah, there are workarounds, but Zack is right. This is really really lame. I understand wanting to have optimizations, but if there is somewhere in code that the developer needs to compare some closures, then simply have the compiler not optimize those particular sections. Or make some kind of additional function of the compiler that enables it to create equality signatures that don't break with freaking optimizations. This is Apple we're talking about here... if they can fit a Xeon into an iMac then they can certainly make closures comparable. Give me a break!

    – CommaToast
    Jul 24 '17 at 9:21



















8














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 = @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





share|improve this answer
























  • Hey , I am trying if unsafeBitCast(listener, AnyObject.self) === unsafeBitCast(f, AnyObject.self) but get fatal error: can't unsafeBitCast between types of different sizes. The idea is to build a event based system but the removeEventListener method should be able to check the function pointers.

    – freezing_
    Jan 28 '15 at 21:19








  • 2





    Use @convention(block) instead of @objc_block on Swift 2.x. Great answer!

    – Gabriel.Massana
    Jun 15 '16 at 10:56





















6





+50









I've been looking for the answer, too. And I've found it at last.




  • https://gist.github.com/dankogai/b03319ce427544beb5a4


What you need is the actual function pointer and its context hidden in the function object.



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
}


And here is the demo:



// 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)")


See the URLs below to find why and how it works:




  • https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift

  • https://github.com/rodionovd/SWRoute/blob/master/SWRoute/rd_get_func_impl.c


As you see it is capable of checking identity only (the 2nd test yields false). But that should be good enough.






share|improve this answer





















  • 3





    This method will not be reliable with compiler optimizations devforums.apple.com/message/1035180#1035180

    – drewag
    Sep 5 '14 at 21:15






  • 5





    This is an hack based on undefined implementation details. Then using this means your program will produce an undefined result.

    – Eonil
    Nov 9 '14 at 20:10






  • 6





    Note that this relies on undocumented stuff, and undisclosed implementation details, which can crash your app in future in they change. Not recommended to be used in production code.

    – Cristik
    Jan 23 '16 at 21:29











  • This is "clover", but completely unworkable. I don't know why this was rewarded a bounty. The language intentionally doesn't have function equality, for the exact purpose of freeing the compiler to break function equality freely in order to yield better optimizations.

    – Alexander
    Jan 3 at 4:44











  • ... and this is exactly the approach Chris Lattner advocates against (see the top answer).

    – pipacs
    Mar 6 at 14:45



















6














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
}))





share|improve this answer



















  • 2





    This is, by far, the best approach. It sucks to have to wrap and unwrap closures, but it's better than nondeterministic, unsupported fragility.

    – Barry
    Jul 3 '16 at 5:22



















4














This is a great question and while Chris Lattner intentionally doesn't want to support this feature I, like many developers, also can't let go of my feelings coming from other languages where this is a trivial task. There are plenty of unsafeBitCast examples, most of them don't show the full picture, here's a more detailed one:



typealias SwfBlock = () -> ()
typealias ObjBlock = @convention(block) () -> ()

func testSwfBlock(a: SwfBlock, _ b: SwfBlock) -> String {
let objA = unsafeBitCast(a as ObjBlock, AnyObject.self)
let objB = unsafeBitCast(b as ObjBlock, AnyObject.self)
return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
}

func testObjBlock(a: ObjBlock, _ b: ObjBlock) -> String {
let objA = unsafeBitCast(a, AnyObject.self)
let objB = unsafeBitCast(b, AnyObject.self)
return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
}

func testAnyBlock(a: Any?, _ b: Any?) -> String {
if !(a is ObjBlock) || !(b is ObjBlock) {
return "a nor b are ObjBlock, they are not equal"
}
let objA = unsafeBitCast(a as! ObjBlock, AnyObject.self)
let objB = unsafeBitCast(b as! ObjBlock, AnyObject.self)
return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
}

class Foo
{
lazy var swfBlock: ObjBlock = self.swf
func swf() { print("swf") }
@objc func obj() { print("obj") }
}

let swfBlock: SwfBlock = { print("swf") }
let objBlock: ObjBlock = { print("obj") }
let foo: Foo = Foo()

print(testSwfBlock(swfBlock, swfBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
print(testSwfBlock(objBlock, objBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false

print(testObjBlock(swfBlock, swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
print(testObjBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

print(testAnyBlock(swfBlock, swfBlock)) // a nor b are ObjBlock, they are not equal
print(testAnyBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

print(testObjBlock(foo.swf, foo.swf)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
print(testSwfBlock(foo.obj, foo.obj)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
print(testAnyBlock(foo.swf, foo.swf)) // a nor b are ObjBlock, they are not equal
print(testAnyBlock(foo.swfBlock, foo.swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true


The interesting part is how swift freely casts SwfBlock to ObjBlock, yet in reality two casted SwfBlock blocks will always be different values, while ObjBlocks won't. When we cast ObjBlock to SwfBlock, the same thing happens to them, they become two different values. So, in order to preserve the reference, this sort of casting should be avoided.



I'm still comprehending this whole subject, but one thing I left wishing for is ability to use @convention(block) on class / struct methods, so I filed a feature request that needs up-voting or explaining why it's a bad idea. I also get a sense this approach might be bad all together, if so, can anyone explain why?






share|improve this answer


























  • I don't think you understand Chris Latner's reasoning as to why this isn't (and shouldn't be) supported. " I also get a sense this approach might be bad all together, if so, can anyone explain why?" Because in an optimized build, the compiler is free to mangle the code in many ways that break the idea of point equality of functions. For a basic example, if one function's body starts the same way another function does, the compiler is likely to overlap the two in the machine code, only keeping different exit points. This reduces duplication

    – Alexander
    Jan 3 at 4:33











  • Fundamentally, closures are ways of initiating objects of anonymous classes (just like in Java, but there's it's more obvious). These closures objects are heap allocated, and store the data captured by the closure, which act like implicit parameter's to the closure's function. The closure object holds a reference to a function which operates upon the explicit (via func args) and implicit (via captured closure context) args. While the function body can be shared as a single unique point, the closure object's pointer can't be, because there's one closure object per set of enclosed values.

    – Alexander
    Jan 3 at 4:37











  • So when you have Struct S { func f(_: Int) -> Bool }, you actually have a function of type S.f which has type (S) -> (Int) -> Bool. This function can be shared. It is solely parameterized by its explicit parameters. By when you use it as an instance method (either by implicitly binding the self parameter by calling the method on an object, e.g. S().f, or by explicitly binding it, e.g. S.f(S())), you create a new closure object. This object stores a pointer to S.f (which can be shared), but also to your instance (self, the S()`).

    – Alexander
    Jan 3 at 4:41











  • This closure object must be unique per instance of S. If closure pointer equality were possible, then you would be surprised to discover that s1.f is not the same pointer as s2.f (because one is a closure object which references s1 and f, and the other is a closure object which references s2 and f).

    – Alexander
    Jan 3 at 4:42











  • This is brilliant, thank you! Yes, by now I had a picture of what's going on and this puts everything into a perspective! 👍

    – Ian Bytchek
    Jan 3 at 7:51



















3














Here is one possible solution (conceptually the same as 'tuncay' answer). The point is to define a class that wraps some functionality (e.g. Command):



Swift:



typealias Callback = (Any...)->Void
class Command {
init(_ fn: @escaping Callback) {
self.fn_ = fn
}

var exec : (_ args: Any...)->Void {
get {
return fn_
}
}
var fn_ :Callback
}

let cmd1 = Command { _ in print("hello")}
let cmd2 = cmd1
let cmd3 = Command { (_ args: Any...) in
print(args.count)
}

cmd1.exec()
cmd2.exec()
cmd3.exec(1, 2, "str")

cmd1 === cmd2 // true
cmd1 === cmd3 // false


Java:



interface Command {
void exec(Object... args);
}
Command cmd1 = new Command() {
public void exec(Object... args) [
// do something
}
}
Command cmd2 = cmd1;
Command cmd3 = new Command() {
public void exec(Object... args) {
// do something else
}
}

cmd1 == cmd2 // true
cmd1 == cmd3 // false





share|improve this answer


























  • This would be much better if you made it Generic.

    – Alexander
    Jan 3 at 4:28



















2














Well it's been 2 days and nobody has chimed in with a solution, so I'll change my comment to an answer:



As far as I can tell, you can't check equality or identity of functions (like your example) and metaclasses (e.g., MyClass.self):



But – and this is just an idea – I can't help but notice that the where clause in generics appears to be able to check equality of types. So maybe you can leverage that, at least for checking identity?






share|improve this answer































    0














    Not a general solution, but if one is trying to implement a listener pattern, I've ended up returning an "id" of the function during the registration so I can use it to unregister later (which is kind of workaround to the original question for "listeners" case as usually unregistering comes down to checking the functions for equality, which is at least not "trivial" as per other answers).



    So something like this:



    class OfflineManager {
    var networkChangedListeners = [String:((Bool) -> Void)]()

    func registerOnNetworkAvailabilityChangedListener(_ listener: @escaping ((Bool) -> Void)) -> String{
    let listenerId = UUID().uuidString;
    networkChangedListeners[listenerId] = listener;
    return listenerId;
    }
    func unregisterOnNetworkAvailabilityChangedListener(_ listenerId: String){
    networkChangedListeners.removeValue(forKey: listenerId);
    }
    }


    Now you just need to store the key returned by the "register" function and pass it when unregistering.






    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f24111984%2fhow-do-you-test-functions-and-closures-for-equality%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      8 Answers
      8






      active

      oldest

      votes








      8 Answers
      8






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      60














      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.






      share|improve this answer



















      • 17





        This just bit me, which was kind of devastating because I had been storing closures in an Array and now can't remove them with indexOf({$0 == closure} so I have to refactor. IMHO optimization shouldn't influence language design, so without a quick fix like the now deprecated @objc_block in matt's answer, I would argue that Swift can't properly store and retrieve closures at this time. So I don't think it's appropriate to advocate the use of Swift in callback heavy code like the kind encountered in web development. Which was the whole reason we switched to Swift in the first place...

        – Zack Morris
        Jan 20 '16 at 23:12






      • 3





        @ZackMorris Store some sort of identifier with the closure so you can remove it later. If you are using reference types you can just store a reference to the object otherwise you can come up with your own identifier system. You could even design a type that has a closure and a unique identifier that you can use instead of a plain closure.

        – drewag
        Jan 21 '16 at 5:36








      • 4





        @drewag Yeah, there are workarounds, but Zack is right. This is really really lame. I understand wanting to have optimizations, but if there is somewhere in code that the developer needs to compare some closures, then simply have the compiler not optimize those particular sections. Or make some kind of additional function of the compiler that enables it to create equality signatures that don't break with freaking optimizations. This is Apple we're talking about here... if they can fit a Xeon into an iMac then they can certainly make closures comparable. Give me a break!

        – CommaToast
        Jul 24 '17 at 9:21
















      60














      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.






      share|improve this answer



















      • 17





        This just bit me, which was kind of devastating because I had been storing closures in an Array and now can't remove them with indexOf({$0 == closure} so I have to refactor. IMHO optimization shouldn't influence language design, so without a quick fix like the now deprecated @objc_block in matt's answer, I would argue that Swift can't properly store and retrieve closures at this time. So I don't think it's appropriate to advocate the use of Swift in callback heavy code like the kind encountered in web development. Which was the whole reason we switched to Swift in the first place...

        – Zack Morris
        Jan 20 '16 at 23:12






      • 3





        @ZackMorris Store some sort of identifier with the closure so you can remove it later. If you are using reference types you can just store a reference to the object otherwise you can come up with your own identifier system. You could even design a type that has a closure and a unique identifier that you can use instead of a plain closure.

        – drewag
        Jan 21 '16 at 5:36








      • 4





        @drewag Yeah, there are workarounds, but Zack is right. This is really really lame. I understand wanting to have optimizations, but if there is somewhere in code that the developer needs to compare some closures, then simply have the compiler not optimize those particular sections. Or make some kind of additional function of the compiler that enables it to create equality signatures that don't break with freaking optimizations. This is Apple we're talking about here... if they can fit a Xeon into an iMac then they can certainly make closures comparable. Give me a break!

        – CommaToast
        Jul 24 '17 at 9:21














      60












      60








      60







      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.






      share|improve this answer













      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.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Sep 5 '14 at 21:15









      drewagdrewag

      73.9k25125122




      73.9k25125122








      • 17





        This just bit me, which was kind of devastating because I had been storing closures in an Array and now can't remove them with indexOf({$0 == closure} so I have to refactor. IMHO optimization shouldn't influence language design, so without a quick fix like the now deprecated @objc_block in matt's answer, I would argue that Swift can't properly store and retrieve closures at this time. So I don't think it's appropriate to advocate the use of Swift in callback heavy code like the kind encountered in web development. Which was the whole reason we switched to Swift in the first place...

        – Zack Morris
        Jan 20 '16 at 23:12






      • 3





        @ZackMorris Store some sort of identifier with the closure so you can remove it later. If you are using reference types you can just store a reference to the object otherwise you can come up with your own identifier system. You could even design a type that has a closure and a unique identifier that you can use instead of a plain closure.

        – drewag
        Jan 21 '16 at 5:36








      • 4





        @drewag Yeah, there are workarounds, but Zack is right. This is really really lame. I understand wanting to have optimizations, but if there is somewhere in code that the developer needs to compare some closures, then simply have the compiler not optimize those particular sections. Or make some kind of additional function of the compiler that enables it to create equality signatures that don't break with freaking optimizations. This is Apple we're talking about here... if they can fit a Xeon into an iMac then they can certainly make closures comparable. Give me a break!

        – CommaToast
        Jul 24 '17 at 9:21














      • 17





        This just bit me, which was kind of devastating because I had been storing closures in an Array and now can't remove them with indexOf({$0 == closure} so I have to refactor. IMHO optimization shouldn't influence language design, so without a quick fix like the now deprecated @objc_block in matt's answer, I would argue that Swift can't properly store and retrieve closures at this time. So I don't think it's appropriate to advocate the use of Swift in callback heavy code like the kind encountered in web development. Which was the whole reason we switched to Swift in the first place...

        – Zack Morris
        Jan 20 '16 at 23:12






      • 3





        @ZackMorris Store some sort of identifier with the closure so you can remove it later. If you are using reference types you can just store a reference to the object otherwise you can come up with your own identifier system. You could even design a type that has a closure and a unique identifier that you can use instead of a plain closure.

        – drewag
        Jan 21 '16 at 5:36








      • 4





        @drewag Yeah, there are workarounds, but Zack is right. This is really really lame. I understand wanting to have optimizations, but if there is somewhere in code that the developer needs to compare some closures, then simply have the compiler not optimize those particular sections. Or make some kind of additional function of the compiler that enables it to create equality signatures that don't break with freaking optimizations. This is Apple we're talking about here... if they can fit a Xeon into an iMac then they can certainly make closures comparable. Give me a break!

        – CommaToast
        Jul 24 '17 at 9:21








      17




      17





      This just bit me, which was kind of devastating because I had been storing closures in an Array and now can't remove them with indexOf({$0 == closure} so I have to refactor. IMHO optimization shouldn't influence language design, so without a quick fix like the now deprecated @objc_block in matt's answer, I would argue that Swift can't properly store and retrieve closures at this time. So I don't think it's appropriate to advocate the use of Swift in callback heavy code like the kind encountered in web development. Which was the whole reason we switched to Swift in the first place...

      – Zack Morris
      Jan 20 '16 at 23:12





      This just bit me, which was kind of devastating because I had been storing closures in an Array and now can't remove them with indexOf({$0 == closure} so I have to refactor. IMHO optimization shouldn't influence language design, so without a quick fix like the now deprecated @objc_block in matt's answer, I would argue that Swift can't properly store and retrieve closures at this time. So I don't think it's appropriate to advocate the use of Swift in callback heavy code like the kind encountered in web development. Which was the whole reason we switched to Swift in the first place...

      – Zack Morris
      Jan 20 '16 at 23:12




      3




      3





      @ZackMorris Store some sort of identifier with the closure so you can remove it later. If you are using reference types you can just store a reference to the object otherwise you can come up with your own identifier system. You could even design a type that has a closure and a unique identifier that you can use instead of a plain closure.

      – drewag
      Jan 21 '16 at 5:36







      @ZackMorris Store some sort of identifier with the closure so you can remove it later. If you are using reference types you can just store a reference to the object otherwise you can come up with your own identifier system. You could even design a type that has a closure and a unique identifier that you can use instead of a plain closure.

      – drewag
      Jan 21 '16 at 5:36






      4




      4





      @drewag Yeah, there are workarounds, but Zack is right. This is really really lame. I understand wanting to have optimizations, but if there is somewhere in code that the developer needs to compare some closures, then simply have the compiler not optimize those particular sections. Or make some kind of additional function of the compiler that enables it to create equality signatures that don't break with freaking optimizations. This is Apple we're talking about here... if they can fit a Xeon into an iMac then they can certainly make closures comparable. Give me a break!

      – CommaToast
      Jul 24 '17 at 9:21





      @drewag Yeah, there are workarounds, but Zack is right. This is really really lame. I understand wanting to have optimizations, but if there is somewhere in code that the developer needs to compare some closures, then simply have the compiler not optimize those particular sections. Or make some kind of additional function of the compiler that enables it to create equality signatures that don't break with freaking optimizations. This is Apple we're talking about here... if they can fit a Xeon into an iMac then they can certainly make closures comparable. Give me a break!

      – CommaToast
      Jul 24 '17 at 9:21













      8














      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 = @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





      share|improve this answer
























      • Hey , I am trying if unsafeBitCast(listener, AnyObject.self) === unsafeBitCast(f, AnyObject.self) but get fatal error: can't unsafeBitCast between types of different sizes. The idea is to build a event based system but the removeEventListener method should be able to check the function pointers.

        – freezing_
        Jan 28 '15 at 21:19








      • 2





        Use @convention(block) instead of @objc_block on Swift 2.x. Great answer!

        – Gabriel.Massana
        Jun 15 '16 at 10:56


















      8














      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 = @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





      share|improve this answer
























      • Hey , I am trying if unsafeBitCast(listener, AnyObject.self) === unsafeBitCast(f, AnyObject.self) but get fatal error: can't unsafeBitCast between types of different sizes. The idea is to build a event based system but the removeEventListener method should be able to check the function pointers.

        – freezing_
        Jan 28 '15 at 21:19








      • 2





        Use @convention(block) instead of @objc_block on Swift 2.x. Great answer!

        – Gabriel.Massana
        Jun 15 '16 at 10:56
















      8












      8








      8







      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 = @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





      share|improve this answer













      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 = @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






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Aug 31 '14 at 17:02









      mattmatt

      332k46543741




      332k46543741













      • Hey , I am trying if unsafeBitCast(listener, AnyObject.self) === unsafeBitCast(f, AnyObject.self) but get fatal error: can't unsafeBitCast between types of different sizes. The idea is to build a event based system but the removeEventListener method should be able to check the function pointers.

        – freezing_
        Jan 28 '15 at 21:19








      • 2





        Use @convention(block) instead of @objc_block on Swift 2.x. Great answer!

        – Gabriel.Massana
        Jun 15 '16 at 10:56





















      • Hey , I am trying if unsafeBitCast(listener, AnyObject.self) === unsafeBitCast(f, AnyObject.self) but get fatal error: can't unsafeBitCast between types of different sizes. The idea is to build a event based system but the removeEventListener method should be able to check the function pointers.

        – freezing_
        Jan 28 '15 at 21:19








      • 2





        Use @convention(block) instead of @objc_block on Swift 2.x. Great answer!

        – Gabriel.Massana
        Jun 15 '16 at 10:56



















      Hey , I am trying if unsafeBitCast(listener, AnyObject.self) === unsafeBitCast(f, AnyObject.self) but get fatal error: can't unsafeBitCast between types of different sizes. The idea is to build a event based system but the removeEventListener method should be able to check the function pointers.

      – freezing_
      Jan 28 '15 at 21:19







      Hey , I am trying if unsafeBitCast(listener, AnyObject.self) === unsafeBitCast(f, AnyObject.self) but get fatal error: can't unsafeBitCast between types of different sizes. The idea is to build a event based system but the removeEventListener method should be able to check the function pointers.

      – freezing_
      Jan 28 '15 at 21:19






      2




      2





      Use @convention(block) instead of @objc_block on Swift 2.x. Great answer!

      – Gabriel.Massana
      Jun 15 '16 at 10:56







      Use @convention(block) instead of @objc_block on Swift 2.x. Great answer!

      – Gabriel.Massana
      Jun 15 '16 at 10:56













      6





      +50









      I've been looking for the answer, too. And I've found it at last.




      • https://gist.github.com/dankogai/b03319ce427544beb5a4


      What you need is the actual function pointer and its context hidden in the function object.



      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
      }


      And here is the demo:



      // 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)")


      See the URLs below to find why and how it works:




      • https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift

      • https://github.com/rodionovd/SWRoute/blob/master/SWRoute/rd_get_func_impl.c


      As you see it is capable of checking identity only (the 2nd test yields false). But that should be good enough.






      share|improve this answer





















      • 3





        This method will not be reliable with compiler optimizations devforums.apple.com/message/1035180#1035180

        – drewag
        Sep 5 '14 at 21:15






      • 5





        This is an hack based on undefined implementation details. Then using this means your program will produce an undefined result.

        – Eonil
        Nov 9 '14 at 20:10






      • 6





        Note that this relies on undocumented stuff, and undisclosed implementation details, which can crash your app in future in they change. Not recommended to be used in production code.

        – Cristik
        Jan 23 '16 at 21:29











      • This is "clover", but completely unworkable. I don't know why this was rewarded a bounty. The language intentionally doesn't have function equality, for the exact purpose of freeing the compiler to break function equality freely in order to yield better optimizations.

        – Alexander
        Jan 3 at 4:44











      • ... and this is exactly the approach Chris Lattner advocates against (see the top answer).

        – pipacs
        Mar 6 at 14:45
















      6





      +50









      I've been looking for the answer, too. And I've found it at last.




      • https://gist.github.com/dankogai/b03319ce427544beb5a4


      What you need is the actual function pointer and its context hidden in the function object.



      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
      }


      And here is the demo:



      // 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)")


      See the URLs below to find why and how it works:




      • https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift

      • https://github.com/rodionovd/SWRoute/blob/master/SWRoute/rd_get_func_impl.c


      As you see it is capable of checking identity only (the 2nd test yields false). But that should be good enough.






      share|improve this answer





















      • 3





        This method will not be reliable with compiler optimizations devforums.apple.com/message/1035180#1035180

        – drewag
        Sep 5 '14 at 21:15






      • 5





        This is an hack based on undefined implementation details. Then using this means your program will produce an undefined result.

        – Eonil
        Nov 9 '14 at 20:10






      • 6





        Note that this relies on undocumented stuff, and undisclosed implementation details, which can crash your app in future in they change. Not recommended to be used in production code.

        – Cristik
        Jan 23 '16 at 21:29











      • This is "clover", but completely unworkable. I don't know why this was rewarded a bounty. The language intentionally doesn't have function equality, for the exact purpose of freeing the compiler to break function equality freely in order to yield better optimizations.

        – Alexander
        Jan 3 at 4:44











      • ... and this is exactly the approach Chris Lattner advocates against (see the top answer).

        – pipacs
        Mar 6 at 14:45














      6





      +50







      6





      +50



      6




      +50





      I've been looking for the answer, too. And I've found it at last.




      • https://gist.github.com/dankogai/b03319ce427544beb5a4


      What you need is the actual function pointer and its context hidden in the function object.



      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
      }


      And here is the demo:



      // 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)")


      See the URLs below to find why and how it works:




      • https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift

      • https://github.com/rodionovd/SWRoute/blob/master/SWRoute/rd_get_func_impl.c


      As you see it is capable of checking identity only (the 2nd test yields false). But that should be good enough.






      share|improve this answer















      I've been looking for the answer, too. And I've found it at last.




      • https://gist.github.com/dankogai/b03319ce427544beb5a4


      What you need is the actual function pointer and its context hidden in the function object.



      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
      }


      And here is the demo:



      // 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)")


      See the URLs below to find why and how it works:




      • https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift

      • https://github.com/rodionovd/SWRoute/blob/master/SWRoute/rd_get_func_impl.c


      As you see it is capable of checking identity only (the 2nd test yields false). But that should be good enough.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Aug 4 '14 at 19:55

























      answered Jul 28 '14 at 17:40









      dankogaidankogai

      1,49997




      1,49997








      • 3





        This method will not be reliable with compiler optimizations devforums.apple.com/message/1035180#1035180

        – drewag
        Sep 5 '14 at 21:15






      • 5





        This is an hack based on undefined implementation details. Then using this means your program will produce an undefined result.

        – Eonil
        Nov 9 '14 at 20:10






      • 6





        Note that this relies on undocumented stuff, and undisclosed implementation details, which can crash your app in future in they change. Not recommended to be used in production code.

        – Cristik
        Jan 23 '16 at 21:29











      • This is "clover", but completely unworkable. I don't know why this was rewarded a bounty. The language intentionally doesn't have function equality, for the exact purpose of freeing the compiler to break function equality freely in order to yield better optimizations.

        – Alexander
        Jan 3 at 4:44











      • ... and this is exactly the approach Chris Lattner advocates against (see the top answer).

        – pipacs
        Mar 6 at 14:45














      • 3





        This method will not be reliable with compiler optimizations devforums.apple.com/message/1035180#1035180

        – drewag
        Sep 5 '14 at 21:15






      • 5





        This is an hack based on undefined implementation details. Then using this means your program will produce an undefined result.

        – Eonil
        Nov 9 '14 at 20:10






      • 6





        Note that this relies on undocumented stuff, and undisclosed implementation details, which can crash your app in future in they change. Not recommended to be used in production code.

        – Cristik
        Jan 23 '16 at 21:29











      • This is "clover", but completely unworkable. I don't know why this was rewarded a bounty. The language intentionally doesn't have function equality, for the exact purpose of freeing the compiler to break function equality freely in order to yield better optimizations.

        – Alexander
        Jan 3 at 4:44











      • ... and this is exactly the approach Chris Lattner advocates against (see the top answer).

        – pipacs
        Mar 6 at 14:45








      3




      3





      This method will not be reliable with compiler optimizations devforums.apple.com/message/1035180#1035180

      – drewag
      Sep 5 '14 at 21:15





      This method will not be reliable with compiler optimizations devforums.apple.com/message/1035180#1035180

      – drewag
      Sep 5 '14 at 21:15




      5




      5





      This is an hack based on undefined implementation details. Then using this means your program will produce an undefined result.

      – Eonil
      Nov 9 '14 at 20:10





      This is an hack based on undefined implementation details. Then using this means your program will produce an undefined result.

      – Eonil
      Nov 9 '14 at 20:10




      6




      6





      Note that this relies on undocumented stuff, and undisclosed implementation details, which can crash your app in future in they change. Not recommended to be used in production code.

      – Cristik
      Jan 23 '16 at 21:29





      Note that this relies on undocumented stuff, and undisclosed implementation details, which can crash your app in future in they change. Not recommended to be used in production code.

      – Cristik
      Jan 23 '16 at 21:29













      This is "clover", but completely unworkable. I don't know why this was rewarded a bounty. The language intentionally doesn't have function equality, for the exact purpose of freeing the compiler to break function equality freely in order to yield better optimizations.

      – Alexander
      Jan 3 at 4:44





      This is "clover", but completely unworkable. I don't know why this was rewarded a bounty. The language intentionally doesn't have function equality, for the exact purpose of freeing the compiler to break function equality freely in order to yield better optimizations.

      – Alexander
      Jan 3 at 4:44













      ... and this is exactly the approach Chris Lattner advocates against (see the top answer).

      – pipacs
      Mar 6 at 14:45





      ... and this is exactly the approach Chris Lattner advocates against (see the top answer).

      – pipacs
      Mar 6 at 14:45











      6














      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
      }))





      share|improve this answer



















      • 2





        This is, by far, the best approach. It sucks to have to wrap and unwrap closures, but it's better than nondeterministic, unsupported fragility.

        – Barry
        Jul 3 '16 at 5:22
















      6














      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
      }))





      share|improve this answer



















      • 2





        This is, by far, the best approach. It sucks to have to wrap and unwrap closures, but it's better than nondeterministic, unsupported fragility.

        – Barry
        Jul 3 '16 at 5:22














      6












      6








      6







      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
      }))





      share|improve this answer













      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
      }))






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Aug 17 '15 at 12:12









      tuncaytuncay

      6111




      6111








      • 2





        This is, by far, the best approach. It sucks to have to wrap and unwrap closures, but it's better than nondeterministic, unsupported fragility.

        – Barry
        Jul 3 '16 at 5:22














      • 2





        This is, by far, the best approach. It sucks to have to wrap and unwrap closures, but it's better than nondeterministic, unsupported fragility.

        – Barry
        Jul 3 '16 at 5:22








      2




      2





      This is, by far, the best approach. It sucks to have to wrap and unwrap closures, but it's better than nondeterministic, unsupported fragility.

      – Barry
      Jul 3 '16 at 5:22





      This is, by far, the best approach. It sucks to have to wrap and unwrap closures, but it's better than nondeterministic, unsupported fragility.

      – Barry
      Jul 3 '16 at 5:22











      4














      This is a great question and while Chris Lattner intentionally doesn't want to support this feature I, like many developers, also can't let go of my feelings coming from other languages where this is a trivial task. There are plenty of unsafeBitCast examples, most of them don't show the full picture, here's a more detailed one:



      typealias SwfBlock = () -> ()
      typealias ObjBlock = @convention(block) () -> ()

      func testSwfBlock(a: SwfBlock, _ b: SwfBlock) -> String {
      let objA = unsafeBitCast(a as ObjBlock, AnyObject.self)
      let objB = unsafeBitCast(b as ObjBlock, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      func testObjBlock(a: ObjBlock, _ b: ObjBlock) -> String {
      let objA = unsafeBitCast(a, AnyObject.self)
      let objB = unsafeBitCast(b, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      func testAnyBlock(a: Any?, _ b: Any?) -> String {
      if !(a is ObjBlock) || !(b is ObjBlock) {
      return "a nor b are ObjBlock, they are not equal"
      }
      let objA = unsafeBitCast(a as! ObjBlock, AnyObject.self)
      let objB = unsafeBitCast(b as! ObjBlock, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      class Foo
      {
      lazy var swfBlock: ObjBlock = self.swf
      func swf() { print("swf") }
      @objc func obj() { print("obj") }
      }

      let swfBlock: SwfBlock = { print("swf") }
      let objBlock: ObjBlock = { print("obj") }
      let foo: Foo = Foo()

      print(testSwfBlock(swfBlock, swfBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
      print(testSwfBlock(objBlock, objBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false

      print(testObjBlock(swfBlock, swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
      print(testObjBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

      print(testAnyBlock(swfBlock, swfBlock)) // a nor b are ObjBlock, they are not equal
      print(testAnyBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

      print(testObjBlock(foo.swf, foo.swf)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
      print(testSwfBlock(foo.obj, foo.obj)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
      print(testAnyBlock(foo.swf, foo.swf)) // a nor b are ObjBlock, they are not equal
      print(testAnyBlock(foo.swfBlock, foo.swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true


      The interesting part is how swift freely casts SwfBlock to ObjBlock, yet in reality two casted SwfBlock blocks will always be different values, while ObjBlocks won't. When we cast ObjBlock to SwfBlock, the same thing happens to them, they become two different values. So, in order to preserve the reference, this sort of casting should be avoided.



      I'm still comprehending this whole subject, but one thing I left wishing for is ability to use @convention(block) on class / struct methods, so I filed a feature request that needs up-voting or explaining why it's a bad idea. I also get a sense this approach might be bad all together, if so, can anyone explain why?






      share|improve this answer


























      • I don't think you understand Chris Latner's reasoning as to why this isn't (and shouldn't be) supported. " I also get a sense this approach might be bad all together, if so, can anyone explain why?" Because in an optimized build, the compiler is free to mangle the code in many ways that break the idea of point equality of functions. For a basic example, if one function's body starts the same way another function does, the compiler is likely to overlap the two in the machine code, only keeping different exit points. This reduces duplication

        – Alexander
        Jan 3 at 4:33











      • Fundamentally, closures are ways of initiating objects of anonymous classes (just like in Java, but there's it's more obvious). These closures objects are heap allocated, and store the data captured by the closure, which act like implicit parameter's to the closure's function. The closure object holds a reference to a function which operates upon the explicit (via func args) and implicit (via captured closure context) args. While the function body can be shared as a single unique point, the closure object's pointer can't be, because there's one closure object per set of enclosed values.

        – Alexander
        Jan 3 at 4:37











      • So when you have Struct S { func f(_: Int) -> Bool }, you actually have a function of type S.f which has type (S) -> (Int) -> Bool. This function can be shared. It is solely parameterized by its explicit parameters. By when you use it as an instance method (either by implicitly binding the self parameter by calling the method on an object, e.g. S().f, or by explicitly binding it, e.g. S.f(S())), you create a new closure object. This object stores a pointer to S.f (which can be shared), but also to your instance (self, the S()`).

        – Alexander
        Jan 3 at 4:41











      • This closure object must be unique per instance of S. If closure pointer equality were possible, then you would be surprised to discover that s1.f is not the same pointer as s2.f (because one is a closure object which references s1 and f, and the other is a closure object which references s2 and f).

        – Alexander
        Jan 3 at 4:42











      • This is brilliant, thank you! Yes, by now I had a picture of what's going on and this puts everything into a perspective! 👍

        – Ian Bytchek
        Jan 3 at 7:51
















      4














      This is a great question and while Chris Lattner intentionally doesn't want to support this feature I, like many developers, also can't let go of my feelings coming from other languages where this is a trivial task. There are plenty of unsafeBitCast examples, most of them don't show the full picture, here's a more detailed one:



      typealias SwfBlock = () -> ()
      typealias ObjBlock = @convention(block) () -> ()

      func testSwfBlock(a: SwfBlock, _ b: SwfBlock) -> String {
      let objA = unsafeBitCast(a as ObjBlock, AnyObject.self)
      let objB = unsafeBitCast(b as ObjBlock, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      func testObjBlock(a: ObjBlock, _ b: ObjBlock) -> String {
      let objA = unsafeBitCast(a, AnyObject.self)
      let objB = unsafeBitCast(b, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      func testAnyBlock(a: Any?, _ b: Any?) -> String {
      if !(a is ObjBlock) || !(b is ObjBlock) {
      return "a nor b are ObjBlock, they are not equal"
      }
      let objA = unsafeBitCast(a as! ObjBlock, AnyObject.self)
      let objB = unsafeBitCast(b as! ObjBlock, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      class Foo
      {
      lazy var swfBlock: ObjBlock = self.swf
      func swf() { print("swf") }
      @objc func obj() { print("obj") }
      }

      let swfBlock: SwfBlock = { print("swf") }
      let objBlock: ObjBlock = { print("obj") }
      let foo: Foo = Foo()

      print(testSwfBlock(swfBlock, swfBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
      print(testSwfBlock(objBlock, objBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false

      print(testObjBlock(swfBlock, swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
      print(testObjBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

      print(testAnyBlock(swfBlock, swfBlock)) // a nor b are ObjBlock, they are not equal
      print(testAnyBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

      print(testObjBlock(foo.swf, foo.swf)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
      print(testSwfBlock(foo.obj, foo.obj)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
      print(testAnyBlock(foo.swf, foo.swf)) // a nor b are ObjBlock, they are not equal
      print(testAnyBlock(foo.swfBlock, foo.swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true


      The interesting part is how swift freely casts SwfBlock to ObjBlock, yet in reality two casted SwfBlock blocks will always be different values, while ObjBlocks won't. When we cast ObjBlock to SwfBlock, the same thing happens to them, they become two different values. So, in order to preserve the reference, this sort of casting should be avoided.



      I'm still comprehending this whole subject, but one thing I left wishing for is ability to use @convention(block) on class / struct methods, so I filed a feature request that needs up-voting or explaining why it's a bad idea. I also get a sense this approach might be bad all together, if so, can anyone explain why?






      share|improve this answer


























      • I don't think you understand Chris Latner's reasoning as to why this isn't (and shouldn't be) supported. " I also get a sense this approach might be bad all together, if so, can anyone explain why?" Because in an optimized build, the compiler is free to mangle the code in many ways that break the idea of point equality of functions. For a basic example, if one function's body starts the same way another function does, the compiler is likely to overlap the two in the machine code, only keeping different exit points. This reduces duplication

        – Alexander
        Jan 3 at 4:33











      • Fundamentally, closures are ways of initiating objects of anonymous classes (just like in Java, but there's it's more obvious). These closures objects are heap allocated, and store the data captured by the closure, which act like implicit parameter's to the closure's function. The closure object holds a reference to a function which operates upon the explicit (via func args) and implicit (via captured closure context) args. While the function body can be shared as a single unique point, the closure object's pointer can't be, because there's one closure object per set of enclosed values.

        – Alexander
        Jan 3 at 4:37











      • So when you have Struct S { func f(_: Int) -> Bool }, you actually have a function of type S.f which has type (S) -> (Int) -> Bool. This function can be shared. It is solely parameterized by its explicit parameters. By when you use it as an instance method (either by implicitly binding the self parameter by calling the method on an object, e.g. S().f, or by explicitly binding it, e.g. S.f(S())), you create a new closure object. This object stores a pointer to S.f (which can be shared), but also to your instance (self, the S()`).

        – Alexander
        Jan 3 at 4:41











      • This closure object must be unique per instance of S. If closure pointer equality were possible, then you would be surprised to discover that s1.f is not the same pointer as s2.f (because one is a closure object which references s1 and f, and the other is a closure object which references s2 and f).

        – Alexander
        Jan 3 at 4:42











      • This is brilliant, thank you! Yes, by now I had a picture of what's going on and this puts everything into a perspective! 👍

        – Ian Bytchek
        Jan 3 at 7:51














      4












      4








      4







      This is a great question and while Chris Lattner intentionally doesn't want to support this feature I, like many developers, also can't let go of my feelings coming from other languages where this is a trivial task. There are plenty of unsafeBitCast examples, most of them don't show the full picture, here's a more detailed one:



      typealias SwfBlock = () -> ()
      typealias ObjBlock = @convention(block) () -> ()

      func testSwfBlock(a: SwfBlock, _ b: SwfBlock) -> String {
      let objA = unsafeBitCast(a as ObjBlock, AnyObject.self)
      let objB = unsafeBitCast(b as ObjBlock, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      func testObjBlock(a: ObjBlock, _ b: ObjBlock) -> String {
      let objA = unsafeBitCast(a, AnyObject.self)
      let objB = unsafeBitCast(b, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      func testAnyBlock(a: Any?, _ b: Any?) -> String {
      if !(a is ObjBlock) || !(b is ObjBlock) {
      return "a nor b are ObjBlock, they are not equal"
      }
      let objA = unsafeBitCast(a as! ObjBlock, AnyObject.self)
      let objB = unsafeBitCast(b as! ObjBlock, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      class Foo
      {
      lazy var swfBlock: ObjBlock = self.swf
      func swf() { print("swf") }
      @objc func obj() { print("obj") }
      }

      let swfBlock: SwfBlock = { print("swf") }
      let objBlock: ObjBlock = { print("obj") }
      let foo: Foo = Foo()

      print(testSwfBlock(swfBlock, swfBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
      print(testSwfBlock(objBlock, objBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false

      print(testObjBlock(swfBlock, swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
      print(testObjBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

      print(testAnyBlock(swfBlock, swfBlock)) // a nor b are ObjBlock, they are not equal
      print(testAnyBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

      print(testObjBlock(foo.swf, foo.swf)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
      print(testSwfBlock(foo.obj, foo.obj)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
      print(testAnyBlock(foo.swf, foo.swf)) // a nor b are ObjBlock, they are not equal
      print(testAnyBlock(foo.swfBlock, foo.swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true


      The interesting part is how swift freely casts SwfBlock to ObjBlock, yet in reality two casted SwfBlock blocks will always be different values, while ObjBlocks won't. When we cast ObjBlock to SwfBlock, the same thing happens to them, they become two different values. So, in order to preserve the reference, this sort of casting should be avoided.



      I'm still comprehending this whole subject, but one thing I left wishing for is ability to use @convention(block) on class / struct methods, so I filed a feature request that needs up-voting or explaining why it's a bad idea. I also get a sense this approach might be bad all together, if so, can anyone explain why?






      share|improve this answer















      This is a great question and while Chris Lattner intentionally doesn't want to support this feature I, like many developers, also can't let go of my feelings coming from other languages where this is a trivial task. There are plenty of unsafeBitCast examples, most of them don't show the full picture, here's a more detailed one:



      typealias SwfBlock = () -> ()
      typealias ObjBlock = @convention(block) () -> ()

      func testSwfBlock(a: SwfBlock, _ b: SwfBlock) -> String {
      let objA = unsafeBitCast(a as ObjBlock, AnyObject.self)
      let objB = unsafeBitCast(b as ObjBlock, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      func testObjBlock(a: ObjBlock, _ b: ObjBlock) -> String {
      let objA = unsafeBitCast(a, AnyObject.self)
      let objB = unsafeBitCast(b, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      func testAnyBlock(a: Any?, _ b: Any?) -> String {
      if !(a is ObjBlock) || !(b is ObjBlock) {
      return "a nor b are ObjBlock, they are not equal"
      }
      let objA = unsafeBitCast(a as! ObjBlock, AnyObject.self)
      let objB = unsafeBitCast(b as! ObjBlock, AnyObject.self)
      return "a is ObjBlock: (a is ObjBlock), b is ObjBlock: (b is ObjBlock), objA === objB: (objA === objB)"
      }

      class Foo
      {
      lazy var swfBlock: ObjBlock = self.swf
      func swf() { print("swf") }
      @objc func obj() { print("obj") }
      }

      let swfBlock: SwfBlock = { print("swf") }
      let objBlock: ObjBlock = { print("obj") }
      let foo: Foo = Foo()

      print(testSwfBlock(swfBlock, swfBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
      print(testSwfBlock(objBlock, objBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false

      print(testObjBlock(swfBlock, swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
      print(testObjBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

      print(testAnyBlock(swfBlock, swfBlock)) // a nor b are ObjBlock, they are not equal
      print(testAnyBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true

      print(testObjBlock(foo.swf, foo.swf)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
      print(testSwfBlock(foo.obj, foo.obj)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
      print(testAnyBlock(foo.swf, foo.swf)) // a nor b are ObjBlock, they are not equal
      print(testAnyBlock(foo.swfBlock, foo.swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true


      The interesting part is how swift freely casts SwfBlock to ObjBlock, yet in reality two casted SwfBlock blocks will always be different values, while ObjBlocks won't. When we cast ObjBlock to SwfBlock, the same thing happens to them, they become two different values. So, in order to preserve the reference, this sort of casting should be avoided.



      I'm still comprehending this whole subject, but one thing I left wishing for is ability to use @convention(block) on class / struct methods, so I filed a feature request that needs up-voting or explaining why it's a bad idea. I also get a sense this approach might be bad all together, if so, can anyone explain why?







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Apr 13 '16 at 19:38

























      answered Feb 3 '16 at 14:45









      Ian BytchekIan Bytchek

      6,10552857




      6,10552857













      • I don't think you understand Chris Latner's reasoning as to why this isn't (and shouldn't be) supported. " I also get a sense this approach might be bad all together, if so, can anyone explain why?" Because in an optimized build, the compiler is free to mangle the code in many ways that break the idea of point equality of functions. For a basic example, if one function's body starts the same way another function does, the compiler is likely to overlap the two in the machine code, only keeping different exit points. This reduces duplication

        – Alexander
        Jan 3 at 4:33











      • Fundamentally, closures are ways of initiating objects of anonymous classes (just like in Java, but there's it's more obvious). These closures objects are heap allocated, and store the data captured by the closure, which act like implicit parameter's to the closure's function. The closure object holds a reference to a function which operates upon the explicit (via func args) and implicit (via captured closure context) args. While the function body can be shared as a single unique point, the closure object's pointer can't be, because there's one closure object per set of enclosed values.

        – Alexander
        Jan 3 at 4:37











      • So when you have Struct S { func f(_: Int) -> Bool }, you actually have a function of type S.f which has type (S) -> (Int) -> Bool. This function can be shared. It is solely parameterized by its explicit parameters. By when you use it as an instance method (either by implicitly binding the self parameter by calling the method on an object, e.g. S().f, or by explicitly binding it, e.g. S.f(S())), you create a new closure object. This object stores a pointer to S.f (which can be shared), but also to your instance (self, the S()`).

        – Alexander
        Jan 3 at 4:41











      • This closure object must be unique per instance of S. If closure pointer equality were possible, then you would be surprised to discover that s1.f is not the same pointer as s2.f (because one is a closure object which references s1 and f, and the other is a closure object which references s2 and f).

        – Alexander
        Jan 3 at 4:42











      • This is brilliant, thank you! Yes, by now I had a picture of what's going on and this puts everything into a perspective! 👍

        – Ian Bytchek
        Jan 3 at 7:51



















      • I don't think you understand Chris Latner's reasoning as to why this isn't (and shouldn't be) supported. " I also get a sense this approach might be bad all together, if so, can anyone explain why?" Because in an optimized build, the compiler is free to mangle the code in many ways that break the idea of point equality of functions. For a basic example, if one function's body starts the same way another function does, the compiler is likely to overlap the two in the machine code, only keeping different exit points. This reduces duplication

        – Alexander
        Jan 3 at 4:33











      • Fundamentally, closures are ways of initiating objects of anonymous classes (just like in Java, but there's it's more obvious). These closures objects are heap allocated, and store the data captured by the closure, which act like implicit parameter's to the closure's function. The closure object holds a reference to a function which operates upon the explicit (via func args) and implicit (via captured closure context) args. While the function body can be shared as a single unique point, the closure object's pointer can't be, because there's one closure object per set of enclosed values.

        – Alexander
        Jan 3 at 4:37











      • So when you have Struct S { func f(_: Int) -> Bool }, you actually have a function of type S.f which has type (S) -> (Int) -> Bool. This function can be shared. It is solely parameterized by its explicit parameters. By when you use it as an instance method (either by implicitly binding the self parameter by calling the method on an object, e.g. S().f, or by explicitly binding it, e.g. S.f(S())), you create a new closure object. This object stores a pointer to S.f (which can be shared), but also to your instance (self, the S()`).

        – Alexander
        Jan 3 at 4:41











      • This closure object must be unique per instance of S. If closure pointer equality were possible, then you would be surprised to discover that s1.f is not the same pointer as s2.f (because one is a closure object which references s1 and f, and the other is a closure object which references s2 and f).

        – Alexander
        Jan 3 at 4:42











      • This is brilliant, thank you! Yes, by now I had a picture of what's going on and this puts everything into a perspective! 👍

        – Ian Bytchek
        Jan 3 at 7:51

















      I don't think you understand Chris Latner's reasoning as to why this isn't (and shouldn't be) supported. " I also get a sense this approach might be bad all together, if so, can anyone explain why?" Because in an optimized build, the compiler is free to mangle the code in many ways that break the idea of point equality of functions. For a basic example, if one function's body starts the same way another function does, the compiler is likely to overlap the two in the machine code, only keeping different exit points. This reduces duplication

      – Alexander
      Jan 3 at 4:33





      I don't think you understand Chris Latner's reasoning as to why this isn't (and shouldn't be) supported. " I also get a sense this approach might be bad all together, if so, can anyone explain why?" Because in an optimized build, the compiler is free to mangle the code in many ways that break the idea of point equality of functions. For a basic example, if one function's body starts the same way another function does, the compiler is likely to overlap the two in the machine code, only keeping different exit points. This reduces duplication

      – Alexander
      Jan 3 at 4:33













      Fundamentally, closures are ways of initiating objects of anonymous classes (just like in Java, but there's it's more obvious). These closures objects are heap allocated, and store the data captured by the closure, which act like implicit parameter's to the closure's function. The closure object holds a reference to a function which operates upon the explicit (via func args) and implicit (via captured closure context) args. While the function body can be shared as a single unique point, the closure object's pointer can't be, because there's one closure object per set of enclosed values.

      – Alexander
      Jan 3 at 4:37





      Fundamentally, closures are ways of initiating objects of anonymous classes (just like in Java, but there's it's more obvious). These closures objects are heap allocated, and store the data captured by the closure, which act like implicit parameter's to the closure's function. The closure object holds a reference to a function which operates upon the explicit (via func args) and implicit (via captured closure context) args. While the function body can be shared as a single unique point, the closure object's pointer can't be, because there's one closure object per set of enclosed values.

      – Alexander
      Jan 3 at 4:37













      So when you have Struct S { func f(_: Int) -> Bool }, you actually have a function of type S.f which has type (S) -> (Int) -> Bool. This function can be shared. It is solely parameterized by its explicit parameters. By when you use it as an instance method (either by implicitly binding the self parameter by calling the method on an object, e.g. S().f, or by explicitly binding it, e.g. S.f(S())), you create a new closure object. This object stores a pointer to S.f (which can be shared), but also to your instance (self, the S()`).

      – Alexander
      Jan 3 at 4:41





      So when you have Struct S { func f(_: Int) -> Bool }, you actually have a function of type S.f which has type (S) -> (Int) -> Bool. This function can be shared. It is solely parameterized by its explicit parameters. By when you use it as an instance method (either by implicitly binding the self parameter by calling the method on an object, e.g. S().f, or by explicitly binding it, e.g. S.f(S())), you create a new closure object. This object stores a pointer to S.f (which can be shared), but also to your instance (self, the S()`).

      – Alexander
      Jan 3 at 4:41













      This closure object must be unique per instance of S. If closure pointer equality were possible, then you would be surprised to discover that s1.f is not the same pointer as s2.f (because one is a closure object which references s1 and f, and the other is a closure object which references s2 and f).

      – Alexander
      Jan 3 at 4:42





      This closure object must be unique per instance of S. If closure pointer equality were possible, then you would be surprised to discover that s1.f is not the same pointer as s2.f (because one is a closure object which references s1 and f, and the other is a closure object which references s2 and f).

      – Alexander
      Jan 3 at 4:42













      This is brilliant, thank you! Yes, by now I had a picture of what's going on and this puts everything into a perspective! 👍

      – Ian Bytchek
      Jan 3 at 7:51





      This is brilliant, thank you! Yes, by now I had a picture of what's going on and this puts everything into a perspective! 👍

      – Ian Bytchek
      Jan 3 at 7:51











      3














      Here is one possible solution (conceptually the same as 'tuncay' answer). The point is to define a class that wraps some functionality (e.g. Command):



      Swift:



      typealias Callback = (Any...)->Void
      class Command {
      init(_ fn: @escaping Callback) {
      self.fn_ = fn
      }

      var exec : (_ args: Any...)->Void {
      get {
      return fn_
      }
      }
      var fn_ :Callback
      }

      let cmd1 = Command { _ in print("hello")}
      let cmd2 = cmd1
      let cmd3 = Command { (_ args: Any...) in
      print(args.count)
      }

      cmd1.exec()
      cmd2.exec()
      cmd3.exec(1, 2, "str")

      cmd1 === cmd2 // true
      cmd1 === cmd3 // false


      Java:



      interface Command {
      void exec(Object... args);
      }
      Command cmd1 = new Command() {
      public void exec(Object... args) [
      // do something
      }
      }
      Command cmd2 = cmd1;
      Command cmd3 = new Command() {
      public void exec(Object... args) {
      // do something else
      }
      }

      cmd1 == cmd2 // true
      cmd1 == cmd3 // false





      share|improve this answer


























      • This would be much better if you made it Generic.

        – Alexander
        Jan 3 at 4:28
















      3














      Here is one possible solution (conceptually the same as 'tuncay' answer). The point is to define a class that wraps some functionality (e.g. Command):



      Swift:



      typealias Callback = (Any...)->Void
      class Command {
      init(_ fn: @escaping Callback) {
      self.fn_ = fn
      }

      var exec : (_ args: Any...)->Void {
      get {
      return fn_
      }
      }
      var fn_ :Callback
      }

      let cmd1 = Command { _ in print("hello")}
      let cmd2 = cmd1
      let cmd3 = Command { (_ args: Any...) in
      print(args.count)
      }

      cmd1.exec()
      cmd2.exec()
      cmd3.exec(1, 2, "str")

      cmd1 === cmd2 // true
      cmd1 === cmd3 // false


      Java:



      interface Command {
      void exec(Object... args);
      }
      Command cmd1 = new Command() {
      public void exec(Object... args) [
      // do something
      }
      }
      Command cmd2 = cmd1;
      Command cmd3 = new Command() {
      public void exec(Object... args) {
      // do something else
      }
      }

      cmd1 == cmd2 // true
      cmd1 == cmd3 // false





      share|improve this answer


























      • This would be much better if you made it Generic.

        – Alexander
        Jan 3 at 4:28














      3












      3








      3







      Here is one possible solution (conceptually the same as 'tuncay' answer). The point is to define a class that wraps some functionality (e.g. Command):



      Swift:



      typealias Callback = (Any...)->Void
      class Command {
      init(_ fn: @escaping Callback) {
      self.fn_ = fn
      }

      var exec : (_ args: Any...)->Void {
      get {
      return fn_
      }
      }
      var fn_ :Callback
      }

      let cmd1 = Command { _ in print("hello")}
      let cmd2 = cmd1
      let cmd3 = Command { (_ args: Any...) in
      print(args.count)
      }

      cmd1.exec()
      cmd2.exec()
      cmd3.exec(1, 2, "str")

      cmd1 === cmd2 // true
      cmd1 === cmd3 // false


      Java:



      interface Command {
      void exec(Object... args);
      }
      Command cmd1 = new Command() {
      public void exec(Object... args) [
      // do something
      }
      }
      Command cmd2 = cmd1;
      Command cmd3 = new Command() {
      public void exec(Object... args) {
      // do something else
      }
      }

      cmd1 == cmd2 // true
      cmd1 == cmd3 // false





      share|improve this answer















      Here is one possible solution (conceptually the same as 'tuncay' answer). The point is to define a class that wraps some functionality (e.g. Command):



      Swift:



      typealias Callback = (Any...)->Void
      class Command {
      init(_ fn: @escaping Callback) {
      self.fn_ = fn
      }

      var exec : (_ args: Any...)->Void {
      get {
      return fn_
      }
      }
      var fn_ :Callback
      }

      let cmd1 = Command { _ in print("hello")}
      let cmd2 = cmd1
      let cmd3 = Command { (_ args: Any...) in
      print(args.count)
      }

      cmd1.exec()
      cmd2.exec()
      cmd3.exec(1, 2, "str")

      cmd1 === cmd2 // true
      cmd1 === cmd3 // false


      Java:



      interface Command {
      void exec(Object... args);
      }
      Command cmd1 = new Command() {
      public void exec(Object... args) [
      // do something
      }
      }
      Command cmd2 = cmd1;
      Command cmd3 = new Command() {
      public void exec(Object... args) {
      // do something else
      }
      }

      cmd1 == cmd2 // true
      cmd1 == cmd3 // false






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Mar 17 '17 at 12:12

























      answered Mar 16 '17 at 16:37









      basobaso

      313




      313













      • This would be much better if you made it Generic.

        – Alexander
        Jan 3 at 4:28



















      • This would be much better if you made it Generic.

        – Alexander
        Jan 3 at 4:28

















      This would be much better if you made it Generic.

      – Alexander
      Jan 3 at 4:28





      This would be much better if you made it Generic.

      – Alexander
      Jan 3 at 4:28











      2














      Well it's been 2 days and nobody has chimed in with a solution, so I'll change my comment to an answer:



      As far as I can tell, you can't check equality or identity of functions (like your example) and metaclasses (e.g., MyClass.self):



      But – and this is just an idea – I can't help but notice that the where clause in generics appears to be able to check equality of types. So maybe you can leverage that, at least for checking identity?






      share|improve this answer




























        2














        Well it's been 2 days and nobody has chimed in with a solution, so I'll change my comment to an answer:



        As far as I can tell, you can't check equality or identity of functions (like your example) and metaclasses (e.g., MyClass.self):



        But – and this is just an idea – I can't help but notice that the where clause in generics appears to be able to check equality of types. So maybe you can leverage that, at least for checking identity?






        share|improve this answer


























          2












          2








          2







          Well it's been 2 days and nobody has chimed in with a solution, so I'll change my comment to an answer:



          As far as I can tell, you can't check equality or identity of functions (like your example) and metaclasses (e.g., MyClass.self):



          But – and this is just an idea – I can't help but notice that the where clause in generics appears to be able to check equality of types. So maybe you can leverage that, at least for checking identity?






          share|improve this answer













          Well it's been 2 days and nobody has chimed in with a solution, so I'll change my comment to an answer:



          As far as I can tell, you can't check equality or identity of functions (like your example) and metaclasses (e.g., MyClass.self):



          But – and this is just an idea – I can't help but notice that the where clause in generics appears to be able to check equality of types. So maybe you can leverage that, at least for checking identity?







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jun 11 '14 at 14:54









          JiaaroJiaaro

          46k32135170




          46k32135170























              0














              Not a general solution, but if one is trying to implement a listener pattern, I've ended up returning an "id" of the function during the registration so I can use it to unregister later (which is kind of workaround to the original question for "listeners" case as usually unregistering comes down to checking the functions for equality, which is at least not "trivial" as per other answers).



              So something like this:



              class OfflineManager {
              var networkChangedListeners = [String:((Bool) -> Void)]()

              func registerOnNetworkAvailabilityChangedListener(_ listener: @escaping ((Bool) -> Void)) -> String{
              let listenerId = UUID().uuidString;
              networkChangedListeners[listenerId] = listener;
              return listenerId;
              }
              func unregisterOnNetworkAvailabilityChangedListener(_ listenerId: String){
              networkChangedListeners.removeValue(forKey: listenerId);
              }
              }


              Now you just need to store the key returned by the "register" function and pass it when unregistering.






              share|improve this answer






























                0














                Not a general solution, but if one is trying to implement a listener pattern, I've ended up returning an "id" of the function during the registration so I can use it to unregister later (which is kind of workaround to the original question for "listeners" case as usually unregistering comes down to checking the functions for equality, which is at least not "trivial" as per other answers).



                So something like this:



                class OfflineManager {
                var networkChangedListeners = [String:((Bool) -> Void)]()

                func registerOnNetworkAvailabilityChangedListener(_ listener: @escaping ((Bool) -> Void)) -> String{
                let listenerId = UUID().uuidString;
                networkChangedListeners[listenerId] = listener;
                return listenerId;
                }
                func unregisterOnNetworkAvailabilityChangedListener(_ listenerId: String){
                networkChangedListeners.removeValue(forKey: listenerId);
                }
                }


                Now you just need to store the key returned by the "register" function and pass it when unregistering.






                share|improve this answer




























                  0












                  0








                  0







                  Not a general solution, but if one is trying to implement a listener pattern, I've ended up returning an "id" of the function during the registration so I can use it to unregister later (which is kind of workaround to the original question for "listeners" case as usually unregistering comes down to checking the functions for equality, which is at least not "trivial" as per other answers).



                  So something like this:



                  class OfflineManager {
                  var networkChangedListeners = [String:((Bool) -> Void)]()

                  func registerOnNetworkAvailabilityChangedListener(_ listener: @escaping ((Bool) -> Void)) -> String{
                  let listenerId = UUID().uuidString;
                  networkChangedListeners[listenerId] = listener;
                  return listenerId;
                  }
                  func unregisterOnNetworkAvailabilityChangedListener(_ listenerId: String){
                  networkChangedListeners.removeValue(forKey: listenerId);
                  }
                  }


                  Now you just need to store the key returned by the "register" function and pass it when unregistering.






                  share|improve this answer















                  Not a general solution, but if one is trying to implement a listener pattern, I've ended up returning an "id" of the function during the registration so I can use it to unregister later (which is kind of workaround to the original question for "listeners" case as usually unregistering comes down to checking the functions for equality, which is at least not "trivial" as per other answers).



                  So something like this:



                  class OfflineManager {
                  var networkChangedListeners = [String:((Bool) -> Void)]()

                  func registerOnNetworkAvailabilityChangedListener(_ listener: @escaping ((Bool) -> Void)) -> String{
                  let listenerId = UUID().uuidString;
                  networkChangedListeners[listenerId] = listener;
                  return listenerId;
                  }
                  func unregisterOnNetworkAvailabilityChangedListener(_ listenerId: String){
                  networkChangedListeners.removeValue(forKey: listenerId);
                  }
                  }


                  Now you just need to store the key returned by the "register" function and pass it when unregistering.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Jan 7 at 23:14

























                  answered Jan 7 at 23:03









                  vir usvir us

                  3,35412735




                  3,35412735






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f24111984%2fhow-do-you-test-functions-and-closures-for-equality%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      REST vs JSON-RPC?

                      generate and download xml file after input submit (php and mysql) - JPK

                      Angular Downloading a file using contenturl with Basic Authentication