This is in response to the frothing post by Jim and also the post that kicked that off from Ruby. I wrote it as a comment on the Ruby blog "Mistaeks I Hav Made".
I wrote a HOM implementation for Smalltalk back in 2002 and I
had the pleasure of sharing some correspondence with the inventor
of Higher Order Messaging - Marcel Weiher. I feel it's important to
always refer back to the genious behind inventions like this.
The original implementation was Marcel's in ObjectiveC and while
it worked, it was no where near as advanced as Marcel had hoped. I
thought that perhaps I could do a little better in Smalltalk.
You can see my code in Cincom's Public Store repository. In the
end, after talking to Marcel, it seems as though Smalltalk did fit
what Marcel was after better and that was encouraging. However, he
then challenged me with the next trick to HOM...
A trick that I've yet to see -anyone- implement. That being, the
item that you are iterating on doesn't have to be the receiver of
the message send.
Here's Marcel's paper on HOM: http://www.metaobject.com/papers/HOM-Presentation.pdf
Some simple HOM examples to set the scene:
people do jump
people collect socialSecurityNumber
people reject age < 18
((people select isAuthorizedToJumpOver: fence) age > 16) reject
hasBrownHair
The tricky stuff starts when you start moving the receiver
around. I had an implementation of this but I felt it didn't add
enough value to compensate for the complexity it introduced:
people deposit: (Receiver of: Bank) amount: 500
This is the equilavent of:
people do: [:person | Bank deposit: person amount: 500]
It's very un-OO to do calls like that but sometimes it is
required. I figure if it's required, then write it in the long hand
instead of the HOM short hand.
Another interesting short-cut kind of syntax that has evolved in
the Smalltalk community is the use of Symbol's instead of blocks,
eg:
people do: #jump
instead of
people do: [:person | person jump]
This works because of the reflective API's in Smalltalk to call
on a block with an argument: #value:. By implementing #value: on a
Symbol, you can do all single message sends -faster- than using a
block.
Oh one more thing, we benchmarked the HOM implementation and it
came up running between 5-10x slower. So if it's non speed critical
code, you may decide to opt for the better HOM syntax. If you don't
have complex collection manip's then you may just like to use the
Symbol trick and actually run faster than normal.
Any way, that's my 25c.
Cheers, Michael