Reputation: 11
I'm trying to construct a table that contains, among other things, an optional closure. When I try to instantiate an instance of the table, passing a member function for the closure I get a compile error.
From the error msg it appears that a member function can not be converted to an optional member function. I don't see why not; an Int or other types can easily be converted to optionals.
struct Foo {
typealias Routine = (_ x: Int) -> Int
let int: Int
let aRoutine: Routine?
init(_ int: Int, _ routine: Routine? = nil) {
self.int = int
self.aRoutine = routine
}
}
class Bar {
let foo = Foo(5, doSomething) // Compile error here
func doSomething(_ x: Int) -> Int {
return x
}
}
Cannot convert value of type '(Bar) -> (Int) -> Int' to expected argument type 'Foo.Routine?' (aka 'Optional<(Int) -> Int>')
Upvotes: 1
Views: 816
Reputation: 63399
You've just discovered that member functions (a.k.a. instance methods) are curried in Swift. See Instance Methods are “Curried” Functions in Swift
Foo.doSomething(_:)
isn't just a free function (a.k.a. global function). It's an instance method that has access to the instance, self
. But if you just take the method as a closure directly, it doesn't know what the value of self
would be.
There are several options:
If your implementation of doSomething(_:)
doesn't need to access self
, then you can move it out of the Foo
's declaration, and declare it as a global function.
Alternatively, you can turn it into a static function by keeping it where it is and using the static
modifier. This has an added benefit over a global function, in that it "organizes" your code by moving it into an appropriate namespace.
If your implementation of doSomething(_:)
does need an instance to operate on, then you can access the unapplied method of that instance. Here's an example. I've added explicit type annotations for demonstration, but you should usually omit those.
let object: Bar = Bar() // an object of type Bar
let boundDoSomethingMethod: (Int) -> Int = object.doSomething // a bound method which operates on `object`
// alternatively:
let unboundDoSomethingMethod: (Bar) -> (Int) -> Int = Bar.doSomething
let boundDoSomethingMethod: (Int) -> Int = unboundDoSomethingMethod(object)
Upvotes: 0