Reputation: 7340
After reading Ole's post http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/
What I understood is that you can call a method of any class in a different context or scope. If I understood it correctly then it's the same as apply
or call
in javascript.
Here's my attempt using this for the Observer pattern.
I've a problem in self.method(self.context)(message)
, the error says (Messaging) -> $T6 is not identical to 'Void'
protocol Messaging {
var message: String { get set }
}
class Observer {
var method: Messaging -> Void
var context: AnyObject
init(method: Messaging -> Void, context: AnyObject) {
self.method = method
self.context = context
}
func notify(message: Messaging) {
self.method(message)
//self.method(self.context)(message) // Houston, we have a problem
}
}
public class Message: Messaging {
var message: String
public init(message: String) {
self.message = message
}
}
class TestObserver {
func createAndNotifiy() {
var observer = Observer(method: self.handleMessage, context: self)
observer.notify(Message(message: "TestMessage"))
}
func handleMessage(message: Messaging) -> Void {
println(message.message)
}
}
var test = TestObserver()
test.createAndNotifiy()
inside notify
method I've attempted to call the passed method in the passed context (I've used context
as self
but it could be a different context too)
My objective is to make it work for any context passed in.
Edit: Is it that who's function I ever pass in, it automatically gets associated to that context, for instance Observer(method: self.handleMessage...
in this case handleMessage
is implicitly/explicitly bound to self
in this case and I shouldn't really care about passing self
as an additional param (as context), cause self.method(message)
calls the method
in context of the bound object automatically? that's my assumption, looking forward to a solid opinion.
but irrespective still also would like to know how to get the curried approach work in this case
Upvotes: 0
Views: 493
Reputation: 40973
There’s a difference between self.methodname
(which you are using), and Classname.methodname
.
The former, when called within a class’s method, will give you a function bound with that class instance. So if you call it, it will be called on that instance.
The latter gives you a curried function that takes as an argument any instance of Classname
, and returns a new function that is bound to that instance. At this point, that function is like the first case (only you can bind it to any instance you like).
Here’s an example to try and show that a bit better:
class C {
private let _msg: String
init(msg: String) { _msg = msg }
func print() { println(_msg) }
func getPrinter() -> ()->() { return self.print }
}
let c = C(msg: "woo-hoo")
let f = c.getPrinter()
// f is of type ()->()
f() // prints "woo-hoo"
let d = C(msg: "way-hey")
let g = C.print
// g is of type (C)->()-(),
// you need to feed it a C:
g(c)() // prints "woo-hoo"
g(d)() // prints "way-hey"
// instead of calling immediately,
// you could store the return of g:
let h = g(c)
// at this point, f and h amount to the same thing:
// h is of type ()->()
h() // prints "woo-hoo"
Finally, looks like you’re trying, with AnyObject
, to take any kind of class and pass that into your curried instance method. That won’t fly – that curried method will specifically need a type of the class it was taken from. No good trying to feed it something else.
Upvotes: 1