I came to know about higher order messages (HOM) - messages that take another message as argument - from here: Higher Order Messaging in Ruby. Then, I read this paper: Higher Order Messaging
To implement higher-order messages with Ruby, two things are usedIn a blog entry, I mentioned about doesNotUnderstand in Groovy. But, there are no open classes in Groovy. But, Groovy supports class categories - a facility by which we can "add" methods to existing classes (within a specific "use" context).
// A class that forwards any message
// to it to the objects of the list
// and returns the result list
class Do {
def list
Do(l) { list = l }
def invokeMethod(String name, args) {
list.collect { it.invokeMethod(name, args) }
}
}
// A class that filters the objects of the list
// using the message invoked on it
class Where {
def list
Where(l) { list = l }
def invokeMethod(String name, args) {
list.findAll { it.invokeMethod(name, args) }
}
}
// A class that sorts the objects of a list
// using the message invoked on it
class Order {
def list
Order(l) { list = l }
def invokeMethod(String name, args) {
list.sort { it.invokeMethod(name, args) }
}
}
// A class category that "adds" methods to List
// class
class ListCategory {
static def getDo(List list) {
return new Do(list);
}
static def getWhere(List list) {
new Where(list);
}
static def getOrderBy(List list) {
new Order(list);
}
}
// we use our List category
use(ListCategory) {
strings = ["JavaScript", "JRuby", "Java", "Groovy", "BeanShell"]
// find all strings that start with "J"
println strings.where.startsWith("J")
// make a list of upper case strings
println strings.do.toUpperCase()
// sort the strings by length
println strings.orderBy.length()
}
As you can see, with higher-order messages, we avoid closures in the method call-chain - making the method chain easily readable.