In Swift 3, What Is a Way to Compare Two Closures

In Swift 5, what is a way to compare pointers to two closures?

About pointers: notably, objects (classes) are reference types, so the equality of two objects is not the same as the identity of two objects. For equality (if defined within the class), you have the == operator, and for identity, the === operator:

class Foo:Equatable {
var i:Int = 0
static func == (lhs: Foo, rhs: Foo) -> Bool {
return lhs.i == rhs.i
}
}

let foo1 = Foo()
let foo2 = Foo()
let referenceToFoo1 = foo1

foo1 == foo2 // equality: true, since foo1.i == foo2.i, which is the criteria for equality
foo1 === foo2 // identity: false, since they are two different instances
foo1 === referenceToFoo1 // identity: true, both variables point to the same instance
foo1.i = 2
print(referenceToFoo1.i) // 2, since it refers to the same object

"Reference" can also be called a "pointer," although in Swift, unlike in C, we don't have to delve into pointer arithmetic, which is a pretty low-level way of dealing with memory addresses of pointers to objects and other data.


Just like classes, closures are also reference types in Swift, so in addition to their "equality" (do they contain the same code and captured information etc.) we can also look into their identity (i.e. do these two variables refer to the same closure or two different ones, even if they look the same etc.).

Problem is, Swift doesn't really seem to want to help us there.

Just like == doesn't work for closures, neither does ===. Neither do closure-types seem to conform to any protocol (and note that there's no single "closure type" but rather an infinite multitude of them depending on parameters and return types).

Furthermore, even casting a closure to AnyObject doesn't work:

foo1 as AnyObject === referenceToFoo1 as AnyObject // true, as expected

// with the `action1` closure from the question:
action1 as AnyObject === action1 as AnyObject // false; a bit of a surprise

Looks like every time Swift casts a closure to AnyObject, it creates a new AnyObject instance for some reason… So comparing these also reveals nothing.

So… I don't think we can reason about the identity or equality of closures in Swift. Maybe there is some other way, possibly via unsafe pointers… well, let me know if anyone had any luck going down that rabbit hole!

Swift and multiple conditions?

More specific, what does

   let char = str.first, condition(char)

do?

Nothing. There is no such expression in your code.

What’s there is this:

guard let char = str.first, condition(char)

That guard makes all the difference. The comma joins two conditions as by nesting, so we have, in effect (since guard is a form of if):

if let char = str.first

and

if condition(char)

You understand both of those well enough, surely? If not, the only remaining thing that might be unfamiliar to you is if let, which is extremely fundamental to Swift and easy to learn about; it unwraps the Optional safely, avoiding the danger of crashing thru an attempt to unwrap nil.

Swift 3 Closure

Why wrap the > in a trailing closure? sorted(by:) takes a function and > already matches its signature. So just do:

let reversedName = names.sorted(by: >)

Just to state maybe non-obvious things:

a) Operators in Swift work like regular functions, e.g. in this case sth like func > <T>(lhs: T, rhs: T) -> Bool

b) In Swift functions are named closures, if an API expects a closure (like (lhs: T, rhs: T) -> Bool), you can also use a named function, like > or func compareTheTwo(a: String, b: String) -> Bool



Related Topics



Leave a reply



Submit