Methods as first class values in Swift
Apparently you can use methods names as first class values in Swift. It must not be a popular feature, I can't find it in the official documentation, but it is there and is just the trick when you want to pass a method selector into a function to, say operate on a complex graph of similarly base classed instances.
The short answer is the "SomeClass.someMethod" gives you a function, which when applied to an instance gives you another function, which when you call that one with the methods arguments (without the labels) invokes the method on the object.
Playground Example
All output is what you'd expect.
//
// A base class and a derived class.
//
class Base {
func blurt( capitalized:Bool) -> String {
return "I am \( capitalized ? "Base" : "base")"
}
}
class Derived : Base {
override func blurt( capitalized:Bool) -> String {
return "I am \( capitalized ? "Derived" : "derived")"
}
}
//
// … an instance of each …
//
let base = Base()
let derived = Derived( )
//
// … they do what you expect …
//
print( base.blurt( capitalized: true ))
print( derived.blurt( capitalized: true ))
//
// HERE BE MAGIC: we grab a value for the method itself,
// it gives us a function which produces a function to
// invoke the method on an instance.
//
// (You can infer the type, I just put it in so
// you can see it.)
//
let m : (Base) -> (Bool) -> String = Base.blurt
//
// Get a function for each of our instances which invokes
// our method.
//
let fDerived : (Bool) -> String = m(derived)
let fBase : (Bool) -> String = m(base)
//
// And invoke them. Notice, we lost our argument names.
//
print( fBase( false) )
print( fDerived( false) )
//
// Once you understand the extra layer of function here,
// you can invoke them like this.
//
print( m(base)(true) )
//
// Limitation: I was unable to tease out a syntax to
// work with polymorphic methods.
//
Open Questions
-
Where is this in the documents?
-
Is there a way to do this with polymorphic methods? By which I mean something like
let m = SomeClass.someMethod( onArray:[Array])
or some such if I havesomeMethod
for both arrays and strings or something.