Ioke will, just as most other dynamic languages, have a way to achieve what Martin Fowler calls Dynamic Reception. For you who are not familiar with this term, it’s the same as the method_missing of Ruby, doesNotUnderstand of Smalltak, __getattr__ of Python, forward of Io, and so on.
It basically allow you to override what happens when the regular message sending fails for some reason. It’s more general in some languages than others. In particular, the Python, Smalltalk and Io versions are more powerful than Ruby’s, since they catch all message sends, not necessarily only those that would cause an invocation.
My problem isn’t really whether I should have it in Ioke. I will have it. It’s extremely useful and allows the implementation of lots of things that can be hard otherwise. The question is what to call it. I’m not totally comfortable with any of the names given to this functionality. I would like to have something that is higher level, basically.
To understand the reasoning behind my thinking, I’ll do a very quick description of the semantic model of Ioke. It’s actually quite simple.
Everything is a message passing. When you write the name of a local variable, you’re sending a message of that name to the current context. When you’re getting the value of something, you are passing a message, etc. Something like this: “foo = 13. foo println”, will first call the message “=”, with foo and 13 as parameters. The next line will send the “foo” message, and then the “println” message to the result of the first one. So in this case it’s obvious that foo is not a method. It’s just a simple value. But if I do this: “foo = method(13). foo println”, the result will be the same, except that when sending the “foo” message, it will actually activate the method inside it. The rule is that when sending a message to get a cell (all the properties/attributes/slots of Ioke are called cells), if that cell returns something that is activatable, it will be activated. There is also a way to get cells without activating them.
So there are two relevant names. Cells and message passing. My first thinking is that since the feature will only be called when a cell can’t be found, it could be called dynamicCell, to reflect that the result is dynamic instead of static. Another version is to just say unhandledMessage, because that is really what happens. A message is sent that no one handles. The third alternative is “forward”, which I like for the metaphor. When someone sends mail to a person not living at an address anymore, the people living there can do something dynamic with it, maybe forward it somewhere.
But I just don’t know which one of these are best… Any suggestions.
14 Comments, Comment or Ping
I’d say ‘forward’ if similarity to Io is at all a virtue to you. I don’t like ‘dynamicCell’.
What advantages does Dynamic Reception have over dynamically defined methods? I went and read what Martin Fowler has to say about it and didn’t see it addressed at all. The only one I can think of is easier proxying, but I think that can be handled better anyways.
November 8th, 2008
forward doesn’t address what is going here, missingMessage or missingCell are more correct in my opinion. But they both are long (14 and 11 chars), maybe only missing or unhandled can be used.
November 8th, 2008
Brennan,
This mechanism is what enables the implementation of stuff like an Ruby’s XML builder:
>> x.date {
?> x.year “2006”
>> x.month “01”
>> x.day “01”
>> }
2006
01
01
I recently built something similar in Python using __getattr__:
print b.date(
b.year(“2006”),
b.month(“01”),
b.day(“01”),
b.numbers(“, “.join([str(x) for x in range(1, 10)]))
)
Output:
2006
01
01
1, 2, 3, 4, 5, 6, 7, 8, 9
November 8th, 2008
I think ‘catch_message’ or ‘on_message’ have good semantics ..
November 8th, 2008
receive? I think the “missing” is just one use case, no need to manifest that in the name.
November 8th, 2008
Are any cells static (i.e. unchangeable at run-time) in Ioke? If not, dynamicCell doesn’t work. Forward would imply (for me) that another (already-defined) cell (of the receiver or some other object) handles the message.
So it should be missingCell or unhandledMessage, I think.
November 8th, 2008
Ola,
I wonder if it is possible to fix the formatting in my previous comment…? I thought everything would be escaped, but instead the tags were simply removed, leaving the examples pointless :-)
By the way, I like the name “missingCell” best. It seems to describe rather precisely what is going on.
November 8th, 2008
You say that “[your] first thinking is that […] the feature will only be called when a cell can’t be found” — how set are you on this? Since I have effectively no experience in language design, I’d love to hear your thoughts on the merits of (a) always catching messages; versus (b) only catching messages when a cell can’t be found; versus (c) letting the programmer specify which.
I have to agree with Radoslav that “forward” doesn’t really seem to fit. I like “missingCell” or “unhandledMessage”, though they are both long. Missing sounds very negative (implies it was somehow -supposed- to be there in the first place), so perhaps abbreviating “unhandledMessage” to “unhandled”? That said, I don’t think anyone would be typing it so frequently as to incur injury, no matter the term chosen. :-)
Other ideas for the fray: otherMessage, filter, noCell[Match].
November 10th, 2008
Unhandled* would strictly be correct but confusing as the point is to handle the message after all. Less confusing, though perhaps a bit too long, are “handleOther” and “otherMessages”.
November 10th, 2008
Objective-C also terms the concept “message forwarding”.
See: http://en.wikipedia.org/wiki/Objective-C#Forwarding
November 11th, 2008
How about “dynamicReceive” ? Given that’s what you are calling this entire feature in your post title…
In the model you have described, you are essentially creating a template pattern – the underlying message receive implementation will search for an appropriate cell, and if it can’t find one it will invoke the abstract “missing” method. Have you considered inverting this – allow the user to simply provide their own message receiving function (override of the parent), which (maybe) would delegate to the default and then provide additional handling if it cannot find a cell?
I’m not really advocating this, just curious if it’s been considered. Personally I think missing_method, et al, has enough scope for causing confusion and complexity in code as it is. But hey – I like statically defined interfaces that can be type checked ;-)
November 11th, 2008
I think the Smalltalk approach makes the most sense to me. Especially if your talking about messages. I didn’t follow where cell came from, but it feels way to close to the implementation. If you’re going to use the term ‘message’, which I think you should, you should stick with it. If I send the message ‘do_long_division’ to a dog, it would be unnatural if the response i got was: ‘could_not_find_cell’, it just doesn’t make sense to me; whereas ‘i_do_not_understand’ is much more natural and cohesive with the world outside of the box. It is not dependent upon knowledge of the implementation to make sense. It gives us something to work with. We can then try more basic messages: ‘bark’, ‘sit’, ‘rollover’. If that doesn’t work we can try sending the messages in other languages, etc. I think even using ‘unhandled_message’ would be too implementation centric. If you ask a crazy person to tie shoes they’re response might be “unhandled message” coupled with a blank stare. At this point we’re not sure if they don’t understand or if they’re just crazy. The appropriate resposne is “i don’t understand,” or “i never learned to tie shoes.”
It would be really cool if you could get to a level where your objects could express a recognition of what is asked of them, but an inability to carry it out, especially if you could then have objects learn from other objects. Oh! You don’t know how to tie shoes, here check it out, this is the code I learned to ite shoes from. Oh, what? You can’t compile Ioke? Here, I can translate it to Java, that should get you going. Or, maybe your object is a jerk. Dude! You don’t know how to tie your shoes? That’s pathetic! /spit
But then again, that’s probably overly idealistic.
November 14th, 2008
How about
“?”
Are objects expected to be able to handle all messages – known and unknown? I mean you have knowledge of messages that can be responded to at run-time during the development phase. And you need at least an abstraction of understanding of how to handle some unknown messages if you wish to do some dynamic things. But in cases where really nothing you can do, the caller should send a “?” message back to the callee.
This opens up a whole new paradigm where not only can messages be received by objects, they can also be sent from one object to another. So you would not only have “slots” of definitions for message receives but for message sending, and responses as well. Messages are not internal functions.
Something like this.
object o
receives: how_are_you
//from being the implicit sender
if from.name==”friend”
i_feel_good(“thanks for asking!”)->from
else
i_feel_good(“, but do I know you?”)->from
end
end
receives: ?
//message being the implicit message body sent. i.e. parameters
if message.is_response
//do some internal stuff for unknown message sends
else
?->from
end
end
sends: i_feel_good(msg)
“Doing good, “+msg
end
object o2
sends: what_is_the_meaning_of end
receives: ?
//message being the implicit message body sent. i.e. parameters
if message.is_response
//some magic internal function
mark_as_clueless(from)
else
?->from
end
end
//one object having a conversation with another
o2.what_is_the_meaning_of(“life”) -> o
//the implicit global object (God?) having a conversation with an object
how_are_you -> o
December 10th, 2008
I don’t know if this is a good idea but for the sake of exploring a different direction:
how about “bin”, “trash”, “void”
My thinking is that “unhandled messages go to the bin/trash/void” the default implementation is to raise an error but you may install new bin if you like to deal with unhanled messages.
Another metafor would be “policy”. The default “unhandled message policy” is to raise an error.
I don’t know, just thinking out loud :)
January 8th, 2009
Reply to “Ioke dynamic reception”