Saturday, September 10, 2005

High Order Messaging

Marcel Weiher sent a mail on the objc mailing-list about a paper he wrote (with Stéphane Ducasse) on High Order Messaging. Basically, HOM is a message that takes another message as a parameter -- like in functional language you have High Order Functions that take a function as parameter.

Ok, nice name .. but why is it interesting ? Well, you have lots of cases where it's really neat :-) but the most known is to use it for iterations. Imagine you have an array containing objects, and you want to send to all of them a message. In Objective-C you'd do:


int i;
for (i=0; i<[myArray count]; i++)
{
id currentElem = [myArray objectAtIndex: i];
[currentElem aMessage];
}

You could also use an enumerator (NSEnumerator) but that doesn't really simplify things. What's the problem with that ? Well, you have code (the for loop..) that you don't really care about, that is actually always the same, you need to deal with each elements, etc. Basically, the programmer's intent is not immediately clear. And of course, the more code you have, the more you can encounteer bugs... So simplifying this pattern would be great. Well, with HOM you will do:

[[myArray do] aMessage];

Better, no ?

Conceptually, the message "do" takes another message as parameter -- it's a HOM. Here it actually bounces the message to all the elements of the array -- therefore, encapsulating the iteration pattern.

Technically, it's a rather cool usage of the Objective-C runtime -- no need to change anything to your compiler :-) -- the HOM message actually returns a Trampoline object that will get the message send to it via forwardInvocation. Read the paper for a good description.

So, using HOM is great for encapsulating the iteration pattern, ok. But after all, we have the makeObjectsPerformSelector.. so why using HOM ?.. Well, the difference is that YOU can create new HOMs, and you are not limited to the iteration pattern :-)

Another good example from the paper.. You have a delegate object you need to send a message to. You'll have the following code:

if ( [delegate respondsToSelector: @selector(windowDidClose:) ]
{
[delegate windowDidClose: self];
}

Again, this is a frequent pattern. Moreover, it's prone to errors -- the selector in the test needs to be equal to the message you send.. An HOM equivalent will be:

[[delegate ifResponds] windowDidClose: self];

Elegant, no ?

Just to finish.. some other examples from the paper:

Starting a method in a thread is done like that in OpenStep:

[NSThread detachNewThreadSelector: @selector(doSomething)
toTarget: receiver withObject: nil];

The HOM equivalent:

[[object async] doSomething];

Or say you want to send a message with a delay.. In OpenStep:

[receiver performSelector: @selector(doSomething)
withObject: nil afterDelay: 1.0];

With HOM:

[[object afterDelay: 1.0] doSomething];


I remember reading about HOM on Marcel's site before this paper, but this paper is an excellent presentation of the idea and do a great job highlighting the possibilities -- another useful mechanism to add to your toolbox to capture patterns :-)

Many HOM implementations exists (in addition to Marcel's original, MPWFoundation), that you can check on that page

Friday, September 02, 2005

PDA, Dynabook and Etoile

I started to think how Etoile could possibly works on -- and take advantage of -- a PDA or Tablet platform...

With the help of Jesse Ross I wrote this page
on the Etoile's wiki; another related page I wrote is one about the Dynabook

Thoughts ?