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

In Swift 5, what is a way to compare pointers to two closures?
I was told here
In Swift 3, what is a way to compare two closures?
that this is somehow a different question.
So now you have it.
public typealias Action = () -> Void
let action1: Action = {}
let action2: Action = {}
assert(action1 == action1)
assert(action1 != action2)

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!

Related

Identity operator can also check whether named types are the same rather only than reference equaliy

As far as I understand, identity operator is used to determine if two objects have the same reference. It means, in practice, the both side of the operator shall be an object.
However, I've tried the following code and it confused me of the identity operator's function of what I understand
class Dog {}
let d: Dog = Dog()
if type(of: d) === Dog.self {
print("yep") //prints out "yep"
}
if type(of: d) == Dog.self {
print("yep") //prints out "yep"
}
The left and right side of the identity operator is not an object but a type and it seems, for this point, semantic equivalence operator and object identity operator (looks like) works in the same way.
Question:
Is this a bug or I didn't get the whole point correctly.
Thanks for your help and time
The left and right side of the identity operator is not an object but a type.
Actually, on Apple platforms, they are objects.
This is due to the fact that Swift classes are implemented as Objective-C classes under the hood, as Mike Ash goes into detail in this great blog post. This means that the metatype of a class is also an Objective-C class, and therefore conforms to AnyObject.
Because of this, you can compare class metatypes with the identity operator, as it's defined as:
public func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool
It'll compare whether the two objects are the same object, or specifically in this case, the same class metatype.
In contrast, under the hood, the metatype for a value type isn't an Objective-C object – it's just a pointer to some static metadata. If we rewrite your example to use a struct:
struct Dog {}
let d = Dog()
// Binary operator '===' cannot be applied to two 'Dog.Type' operands
if type(of: d) === Dog.self {
print("yep")
}
You'll see that we can no longer use === to compare metatypes, as they don't conform to AnyObject. So really, the ability to use the identity operator to compare class metatypes is just a side-effect of them being implemented as Objective-C objects.
The universal way of comparing metatypes is with the equality operator ==, as Swift provides an overload specifically for metatypes:
public func ==(t0: Any.Type?, t1: Any.Type?) -> Bool
This checks whether two metatypes are the same, however unlike ===, it works with both class metatypes and value-typed metatypes. Under the hood, it's implemented as a simple pointer comparison, so should always yield identical results as === with class metatypes.
I would therefore always recommend comparing metatypes with ==, as you're not relying on the conformance to AnyObject. For example, on a Linux platform, class metatypes don't conform to AnyObject and therefore cannot be compared with the identity operator (although interestingly, when Foundation is imported, it appears to add a === overload for AnyObject.Type operands – presumably to aid interoperability).
Not a bug, they are the same thing.
Dog, as a class (type) is a singular, there can only be one. There can be many Instances but only one of the Class.
type(of: d) return the owner Class of d, Dog.self returns the Class itself. They are exactly the same object, the singular Class of Dog.

Swift uses the wrong equality function to determine if an array contains an object [duplicate]

I have a custom operator defined globally like so:
func ==(lhs: Item!, rhs: Item!)->Bool {
return lhs?.dateCreated == rhs?.dateCreated
}
And if I execute this code:
let i1 = Item()
let i2 = Item()
let date = Date()
i1.dateCreated = date
i2.dateCreated = date
let areEqual = i1 == i2
areEqual is false. In this case I know for sure that my custom operator is not firing. However, if I add this code into the playground:
//same function
func ==(lhs: Item!, rhs: item!)->Bool {
return lhs?.dateCreated == rhs?.dateCreated
}
//same code
let i1 = Item()
let i2 = Item()
let date = Date()
i1.dateCreated = date
i2.dateCreated = date
let areEqual = i1 == i2
areEqual is true -- I'm assuming my custom operator is fired in this case.
I have no other custom operators defined that would cause a conflict in the non-playground case, and the Item class is the same in both cases, so why is my custom operator not being called outside the playground?
The Item class inherits from the Object class provided by Realm, which eventually inherits from NSObject. I also noticed that if I define non-optional inputs for the overload, when the inputs are optionals it's not fired.
There are two main problems with what you're trying to do here.
1. Overload resolution favours supertypes over optional promotion
You've declared your == overload for Item! parameters rather than Item parameters. By doing so, the type checker is weighing more in favour of statically dispatching to NSObject's overload for ==, as it appears that the type checker favours subclass to superclass conversions over optional promotion (I haven't been able to find a source to confirm this though).
Usually, you shouldn't need to define your own overload to handle optionals. By conforming a given type to Equatable, you'll automatically get an == overload which handles equality checking between optional instances of that type.
A simpler example that demonstrates the favouring of a superclass overload over an optional subclass overload would be:
// custom operator just for testing.
infix operator <===>
class Foo {}
class Bar : Foo {}
func <===>(lhs: Foo, rhs: Foo) {
print("Foo's overload")
}
func <===>(lhs: Bar?, rhs: Bar?) {
print("Bar's overload")
}
let b = Bar()
b <===> b // Foo's overload
If the Bar? overload is changed to Bar – that overload will be called instead.
Therefore you should change your overload to take Item parameters instead. You'll now be able to use that overload to compare two Item instances for equality. However, this won't fully solve your problem due to the next issue.
2. Subclasses can't directly re-implement protocol requirements
Item doesn't directly conform to Equatable. Instead, it inherits from NSObject, which already conforms to Equatable. Its implementation of == just forwards onto isEqual(_:) – which by default compares memory addresses (i.e checks to see if the two instances are the exact same instance).
What this means is that if you overload == for Item, that overload is not able to be dynamically dispatched to. This is because Item doesn't get its own protocol witness table for conformance to Equatable – it instead relies on NSObject's PWT, which will dispatch to its == overload, simply invoking isEqual(_:).
(Protocol witness tables are the mechanism used in order to achieve dynamic dispatch with protocols – see this WWDC talk on them for more info.)
This will therefore prevent your overload from being called in generic contexts, including the aforementioned free == overload for optionals – explaining why it doesn't work when you attempt to compare Item? instances.
This behaviour can be seen in the following example:
class Foo : Equatable {}
class Bar : Foo {}
func ==(lhs: Foo, rhs: Foo) -> Bool { // gets added to Foo's protocol witness table.
print("Foo's overload") // for conformance to Equatable.
return true
}
func ==(lhs: Bar, rhs: Bar) -> Bool { // Bar doesn't have a PWT for conformance to
print("Bar's overload") // Equatable (as Foo already has), so cannot
return true // dynamically dispatch to this overload.
}
func areEqual<T : Equatable>(lhs: T, rhs: T) -> Bool {
return lhs == rhs // dynamically dispatched via the protocol witness table.
}
let b = Bar()
areEqual(lhs: b, rhs: b) // Foo's overload
So, even if you were to change your overload such that it takes an Item input, if == was ever called from a generic context on an Item instance, your overload won't get called. NSObject's overload will.
This behaviour is somewhat non-obvious, and has been filed as a bug – SR-1729. The reasoning behind it, as explained by Jordan Rose is:
[...] The subclass does not get to provide new members to satisfy the conformance. This is important because a protocol can be added to a base class in one module and a subclass created in another module.
Which makes sense, as the module in which the subclass resides would have to be recompiled in order to allow it to satisfy the conformance – which would likely result in problematic behaviour.
It's worth noting however that this limitation is only really problematic with operator requirements, as other protocol requirements can usually be overridden by subclasses. In such cases, the overriding implementations are added to the subclass' vtable, allowing for dynamic dispatch to take place as expected. However, it's currently not possible to achieve this with operators without the use of a helper method (such as isEqual(_:)).
The Solution
The solution therefore is to override NSObject's isEqual(_:) method and hash property rather than overloading == (see this Q&A for how to go about this). This will ensure that your equality implementation will always be called, regardless of the context – as your override will be added to the class' vtable, allowing for dynamic dispatch.
The reasoning behind overriding hash as well as isEqual(_:) is that you need to maintain the promise that if two objects compare equal, their hashes must be the same. All sorts of weirdness can occur otherwise, if an Item is ever hashed.
Obviously, the solution for non-NSObject derived classes would be to define your own isEqual(_:) method, and have subclasses override it (and then just have the == overload chain to it).

== overload for custom class is not always called

I have a custom operator defined globally like so:
func ==(lhs: Item!, rhs: Item!)->Bool {
return lhs?.dateCreated == rhs?.dateCreated
}
And if I execute this code:
let i1 = Item()
let i2 = Item()
let date = Date()
i1.dateCreated = date
i2.dateCreated = date
let areEqual = i1 == i2
areEqual is false. In this case I know for sure that my custom operator is not firing. However, if I add this code into the playground:
//same function
func ==(lhs: Item!, rhs: item!)->Bool {
return lhs?.dateCreated == rhs?.dateCreated
}
//same code
let i1 = Item()
let i2 = Item()
let date = Date()
i1.dateCreated = date
i2.dateCreated = date
let areEqual = i1 == i2
areEqual is true -- I'm assuming my custom operator is fired in this case.
I have no other custom operators defined that would cause a conflict in the non-playground case, and the Item class is the same in both cases, so why is my custom operator not being called outside the playground?
The Item class inherits from the Object class provided by Realm, which eventually inherits from NSObject. I also noticed that if I define non-optional inputs for the overload, when the inputs are optionals it's not fired.
There are two main problems with what you're trying to do here.
1. Overload resolution favours supertypes over optional promotion
You've declared your == overload for Item! parameters rather than Item parameters. By doing so, the type checker is weighing more in favour of statically dispatching to NSObject's overload for ==, as it appears that the type checker favours subclass to superclass conversions over optional promotion (I haven't been able to find a source to confirm this though).
Usually, you shouldn't need to define your own overload to handle optionals. By conforming a given type to Equatable, you'll automatically get an == overload which handles equality checking between optional instances of that type.
A simpler example that demonstrates the favouring of a superclass overload over an optional subclass overload would be:
// custom operator just for testing.
infix operator <===>
class Foo {}
class Bar : Foo {}
func <===>(lhs: Foo, rhs: Foo) {
print("Foo's overload")
}
func <===>(lhs: Bar?, rhs: Bar?) {
print("Bar's overload")
}
let b = Bar()
b <===> b // Foo's overload
If the Bar? overload is changed to Bar – that overload will be called instead.
Therefore you should change your overload to take Item parameters instead. You'll now be able to use that overload to compare two Item instances for equality. However, this won't fully solve your problem due to the next issue.
2. Subclasses can't directly re-implement protocol requirements
Item doesn't directly conform to Equatable. Instead, it inherits from NSObject, which already conforms to Equatable. Its implementation of == just forwards onto isEqual(_:) – which by default compares memory addresses (i.e checks to see if the two instances are the exact same instance).
What this means is that if you overload == for Item, that overload is not able to be dynamically dispatched to. This is because Item doesn't get its own protocol witness table for conformance to Equatable – it instead relies on NSObject's PWT, which will dispatch to its == overload, simply invoking isEqual(_:).
(Protocol witness tables are the mechanism used in order to achieve dynamic dispatch with protocols – see this WWDC talk on them for more info.)
This will therefore prevent your overload from being called in generic contexts, including the aforementioned free == overload for optionals – explaining why it doesn't work when you attempt to compare Item? instances.
This behaviour can be seen in the following example:
class Foo : Equatable {}
class Bar : Foo {}
func ==(lhs: Foo, rhs: Foo) -> Bool { // gets added to Foo's protocol witness table.
print("Foo's overload") // for conformance to Equatable.
return true
}
func ==(lhs: Bar, rhs: Bar) -> Bool { // Bar doesn't have a PWT for conformance to
print("Bar's overload") // Equatable (as Foo already has), so cannot
return true // dynamically dispatch to this overload.
}
func areEqual<T : Equatable>(lhs: T, rhs: T) -> Bool {
return lhs == rhs // dynamically dispatched via the protocol witness table.
}
let b = Bar()
areEqual(lhs: b, rhs: b) // Foo's overload
So, even if you were to change your overload such that it takes an Item input, if == was ever called from a generic context on an Item instance, your overload won't get called. NSObject's overload will.
This behaviour is somewhat non-obvious, and has been filed as a bug – SR-1729. The reasoning behind it, as explained by Jordan Rose is:
[...] The subclass does not get to provide new members to satisfy the conformance. This is important because a protocol can be added to a base class in one module and a subclass created in another module.
Which makes sense, as the module in which the subclass resides would have to be recompiled in order to allow it to satisfy the conformance – which would likely result in problematic behaviour.
It's worth noting however that this limitation is only really problematic with operator requirements, as other protocol requirements can usually be overridden by subclasses. In such cases, the overriding implementations are added to the subclass' vtable, allowing for dynamic dispatch to take place as expected. However, it's currently not possible to achieve this with operators without the use of a helper method (such as isEqual(_:)).
The Solution
The solution therefore is to override NSObject's isEqual(_:) method and hash property rather than overloading == (see this Q&A for how to go about this). This will ensure that your equality implementation will always be called, regardless of the context – as your override will be added to the class' vtable, allowing for dynamic dispatch.
The reasoning behind overriding hash as well as isEqual(_:) is that you need to maintain the promise that if two objects compare equal, their hashes must be the same. All sorts of weirdness can occur otherwise, if an Item is ever hashed.
Obviously, the solution for non-NSObject derived classes would be to define your own isEqual(_:) method, and have subclasses override it (and then just have the == overload chain to it).

Are there any possible explicit uses of instances (values) of empty tuples (), i.e., of instances of typealias 'Void'?

Question:
Are there any possible explicit uses for the empty tuple (), as a value (and not as a type) in Swift 2.x?
I know that these empty tuples can be used in the standard sense to define void functions. When I mistakenly defined a variable with a empty tuple value var a = () (of type ()), I started wondering if these empty tuple values can be used in some context. Does anyone know of such an application?
Example: possible application with array and optionals?
As an example, we can create an optional array of empty tuples that, naturally, can only hold either nil or ():
/* Optionals */
var foo: ()? = ()
print(foo.dynamicType) // Optional<()>
var arr : [()?] = [foo]
for i in 2...8 {
if i%2 == 0 {
arr.append(nil)
}
else {
arr.append(foo)
}
}
print(arr) // [Optional(()), nil, Optional(()), ... ]
With the small memory footprint of empty tuple, this could seem neat for micro-memory-management for a "boolean nil/not nil", but since type Bool have the same small footprint, I can't really see any direct use here, even in the (unlike) scenario that we really need to go bit-low optimization on our operations.
Perhaps I'm just chasing my own tail with some narrow unusable applications, but anyway: are there any possible explicit uses for these void () beings (as instances, not types)?
There are lots of places that () can be useful when playing around with "CS" problems, which often have the form "implement X using Y even though you really already have X." So for instance, I might say, implement Set using Dictionary. Well, a Dictionary is a Key/Value pair. What should the type of the Value be? I've actually seen this done in languages that have Dictionaries but not Sets, and people often use 1 or true as the value. But that's not really what you mean. That opens up ambiguity. What if the value is false? Is it in the set or not? The right way to implement Set in terms of Dictionary is as [Key: ()], and then you wind up with lines of code like:
set[key] = ()
There are other, equivalent versions, like your Optional<()>. I could also implement integers as [()] or Set<()>. It's a bit silly, but I've done things like that to explore number theory before.
That said, these are all almost intentionally impractical solutions. How about a practical one? Those usually show up when in generic programming. For example, imagine a function with this kind of form:
func doThingAndReturn<T>(retval: T, f: () -> Void) -> T {
f()
return retval
}
This isn't as silly as it sounds. Something along these lines could easily show up in a Command pattern. But what if there's no retval; I don't care about the return? Well, that's fine, just pass a () value.
func doThing(f: () -> Void) {
doThingAndReturn((), f: f)
}
Similarly, you might want a function like zipMap:
func zipMap<T, U>(funcs: [(T) -> U], vals: [T]) -> [U] {
return zip(funcs, vals).map { $0($1) }
}
This applies a series of functions that take T to values of type T. We could use that even if T happens to (), but we'd have to generate a bunch of () values to make that work. For example:
func gen<T>(funcs: [() -> T]) -> [T] {
return zipMap(funcs, vals: Array(count: funcs.count, repeatedValue: ()))
}
I wouldn't expect this to come up very often in Swift because Swift is mostly an imperative language and hides its Void in almost all cases. But you really do see things like this show up in functional languages like Scala when they bridge over into imperative programming.
Suppose you have two functions overloading the same name:
func foo()
func foo() -> Int
The first doesn't return anything, the second returns some kind of value. Attempting to call either of these will in most cases get you a compiler error about ambiguity.
foo()
let a = foo()
You'd think that the compiler would know that the first call unambiguously refers to the first function, because it assumes no return value. But in actuality, the return type of a function with no declared return type is Void, or (). So the first call is actually more like this:
let _ = foo()
And absent a type annotation for the discarded lvalue, the compiler can't infer which foo to call. You can use explicit type annotations to disambiguate:
let b: Void = foo()
let c: Int = foo()
Okay, it's not a very great or common use case for Void, because it's a situation you'd tend to avoid getting into in the first place. But you asked for a use... and it is a use of () as a value and not just a type, because you can retrieve it from b after assignment (for all the good that does you).
Just beware, when you look deeply into the Void, the Void also looks into you. Or something like that.

Filter function syntax?

This works:
func removeObject<T : Equatable>(object: T, array: [T]) -> Array<T>
{
return array.filter() { $0 != object }
}
let threeThings = ["one", "two", "three"]
twoThings = removeObject("three", threeThings)
However, I'd like to check for inequality with this !==. Then I get error "Type 'T' does not conform to protocol 'AnyObject'"
How can this code be fixed? (I've see the code here but I'd like to learn how to use filter properly).
The identical operator === and its negation !== are only defined for
instances of classes, i.e. instances of AnyObject:
func removeObject<T : AnyObject>(object: T, array: [T]) -> Array<T>
{
return array.filter() { $0 !== object }
}
=== checks if two variables refer to the same single instance.
Note that your code
let threeThings = ["one", "two", "three"]
twoThings = removeObject("three", threeThings)
does still compile and run, but gives the (perhaps unexpected) result
[one, two, three]
The Swift strings (which are value types and not class types) are automatically
bridged to NSString, and the two instances of NSString representing "three"
need not be the same.
If you want to use !== instead of !=, then, instead of the type constraint <T : Equatable> say <T : AnyObject>. All you have to do is listen to what the error message is telling you!
Note that this has nothing to do with using the filter function. It is simply a matter of types. You cannot use a method with an object of a type for which that method is not implemented. !== is implemented for AnyObject so if you want to use it you must guarantee to the compiler that this type will be an AnyObject. That is what the type constraint does.
!== checks for "identity", not "equality". Identity is a property of reference types which all support the AnyObject protocol, and it means that the two variables that you are comparing point to the same actual object, and not just another object with the same value.
That means you can't use === or !== with normal value types, like strings, integers, arrays, etc.
Try typing this into a playground:
let a = "yes"
let b = a
println(a === b)
You should get a message saying that String doesn't conform to the AnyObject protocol, because String is a value type (a struct) and doesn't support AnyObject, so you can't use === with it.
You can use === with any instance of a class, because classes are reference types, not value types.
You could put a constraint on T requiring that it conform to AnyObject.
func removeObject<T : Equatable where T: AnyObject>...
It should work, then, for reference types (including all class instances). But then your function won't work for value types (which include all structs).
Why do you need to check for identity (===) instead of equality (==)?