My Groovy HOM – take 2

Posted by Warner Onstine on April 27, 2007

Alright, so I lied. I decided to use this example elsewhere and definitely needed something more flexible. So I spent a couple of hours (and one weird Groovy compilation bug later) and got my HOM implementation so that it uses closures to find stuff. It still uses findAll, but now it makes the determination from the closure passed into it. Now, theoretically you can implement any “message” you want and associate it with a closure in ArrayListMetaClass and voila you have a new operator for any collection. Of course HOM should be more flexible as well, but that I will leave up to others as far as implementation (unless the bug bites me again and I want to expand it a bit more).

Here then is the new relevant code for ArrayListMetaClass:

def whereClosure = { method, args, item ->
    List list = InvokerHelper.asList(args);
    if(list.size() == 0) {
        if( item."${method}"() ) {
            return item
        }
    } else {
        if( item."${method}"(args) ) {
            return item
        }
    }
}

def unlessClosure = { method, args, item ->
    List list = InvokerHelper.asList(args);
    if(list.size() == 0) {
        if(!item."${method}"() ) {
            return item
        }
    } else {
        if(!item."${method}"(args) ) {
            return item
        }
    }
}

def queryTypes = ['where': whereClosure, 'unless': unlessClosure]

def Object getProperty(Object obj, String prop) {
    if(queryTypes.containsKey(prop)) {
        this.hom = new HigherOrderMessage(obj, queryTypes.get(prop))
        return this.hom
    } else {
        return super.getProperty(obj, prop);
    }
}

So, the new items that you’ll notice here is that I decided to go with the closure idea and created two new closures. The whereClosure takes three arguments, the method we’re calling, the arguments to that method and the actual item that needs to get called. Here’s what happens when this closure gets passed in to the HOM object:

def Object invokeMethod(String methodName, arguments) {
    def closure = this.prop.curry(methodName, arguments)
    return this.object.findAll(closure)
}

What we are doing is currying the closure that was passed in and setting the method name and arguments (as they are passed in to invokeMethod) and then passes the curried closure into the findAll() method. Of course I’ve added in a new unit test as well to test my new unlessClosure.

    newList = list.unless.retired()
    assert newList.size() == 3
    assert newList == nonRetiredCollection()

Again, if you want the code, you can grab it here

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

My Groovy HOM 2

Posted by Warner Onstine on April 22, 2007

A friend of mine sent me this link a while back on Higher Order Messaging in Ruby, which tracks back to this original post on HOM in Ruby and eventually tracks back to a presentation given on HOM in Objective-C.

After reading the original post I decided to try my hand at a HOM in Groovy. For me it was mostly a learning experience so that I could get my feet wet with attempting to write a DSL. And it was a great learning experience, unfortunately there are a few stumbling blocks for my implementation in the Groovy language. But without further ado he is my very rough stab at it (You are welcome to take this code and make something more of it, as I stated this was primarily a learning experience and I have no real desire at this point to take it further).

Here then is what I did, first with the test case:

void testHOM() {
    def list = createCollection()
    def newList = list.findAll{ boomer -> boomer.retired()}
    assert newList.size() == 5

    list = createCollection()
    newList = list.where.retired()
    assert newList.size() == 5
}

def createCollection() {
    List boomers = [ new Claimant(name:"Joe", age:65, gender:"M"),
                     new Claimant(name:"Jan", age:61, gender:"F"),
                     new Claimant(name:"Bob", age:50, gender:"M"),
                     new Claimant(name:"Ana", age:60, gender:"F"),
                     new Claimant(name:"Tim", age:60, gender:"M"),
                     new Claimant(name:"May", age:65, gender:"F"),
                     new Claimant(name:"Fay", age:59, gender:"F"),
                     new Claimant(name:"Jay", age:70, gender:"M") ]
    return boomers;
}

The first part simply shows that we are looking through all of the retired claimants, which is decided by this code in Claimant.groovy:

def boolean retired() {
    return (((gender == "M") && (age >= 65)) || ((gender == "F") && (age >= 60)))

}

The second part is where we actually start using Higher Order Messaging. What is the idea behind HOM?

In short the idea is to provide a way to pass messages to objects (in this case “where”) and let the object deal with it (in this case by calling the retired() method on each item in the collection. Let’s take a look at how to actually do that. First we need to create a MetaClass that will intercept method calls (although not all method calls are intercepted which I have filed a bug on already). Here is the HigherOrderMessage object that will get returned when where is called.

package hom;

import org.codehaus.groovy.runtime.InvokerHelper

class HigherOrderMessage {
    def object
    def prop

    def HigherOrderMessage(obj, prop) {
        this.object = obj
        this.prop = prop
    }

    def Object invokeMethod(String methodName, arguments) {
        List list = InvokerHelper.asList(arguments);
        println list
        if(list.size() == 0) {
            return this.object.findAll{item -> item."${methodName}"()}
        }
        return this.object.findAll{item -> item."${methodName}"(arguments)}
    }
}

This helps us keep track of what object we are currently working on within a given HOM (in our case a collection of Claimants and it also helps us track what operation to perform on them, where in this case. As I said earlier, this is an extremely simple implementation, this could greatly be expanded to do a number of things and this implementation is by no means the most ideal (for instance you don’t want to keep track of where, you really should have a closure or something else, hopefully you get the idea).

As you can see by my poor code example, I’m not even checking to see what operation we’re performing, quite honestly I got fed up with some stuff and just wanted something that worked, so you get to see my poor code ;-) . But essentially all this class does is call the actual method that is tacked on to the end of the HOM call list.where.retired() on each item in the collection using Groovy’s closure for findAll.

Next, is the actual part that intercepts the where property call and returns this object, ArrayListMetaClass.

package groovy.runtime.metaclass.java.util

import groovy.lang.DelegatingMetaClass
import groovy.lang.MetaClassRegistry
import org.codehaus.groovy.runtime.InvokerHelper
import hom.HigherOrderMessage

class ArrayListMetaClass extends DelegatingMetaClass {
    def parent
    def collection
    def hom
    def queryTypes = ['where', 'unless']

    ArrayListMetaClass(final Class myClass) {
        super(myClass)
        initialize()
    }

    ArrayListMetaClass(MetaClassRegistry registry, final Class myClass) {
        super(myClass)
    }

    def Object getProperty(Object obj, String prop) {
        if(queryTypes.contains(prop)) {
            this.hom = new HigherOrderMessage(obj, prop)
            return this.hom
        } else {
            return super.getProperty(obj, prop);
        }
    }
}

This class intercepts all calls to ArrayList through some Groovy magic. First there is the name itself ArrayListMetaClass, and the second is the package it lives in groovy.runtime.metaclass.java.util (it actually took me a couple of tries to get this right, originally I put it in groovy.runtime.metaclass.java.lang which only works for classes in that package, so make sure you just prepend the groovy.runtime.metaclass to whatever Java package you need to drop it in, or your own package for that matter).

Once it has intercepted the where property call it then returns a HOM object that we saw earlier. This could of course be extended to embed a closure instead of a simple string to the HOM and then it would be extremely flexible.

All in all this was an extremely interesting exercise and got me much deeper into the Groovy internals and jazzed about the DSLs that I need to write (currently working on those, will post more as I get some code ready for sharing). If you are interested in my poor code, you can grab it here.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Why I won’t be buying an iPhone 1

Posted by Warner Onstine on April 21, 2007

Yeah, I know that this seems really behind the times, and it is. I started writing this just after the iPhone announcement and then forgot about it altogether. But given the fact that I’m looking at phones again, this irks me to no end. T-Mobile’s selections for phones just plain sucks, and honestly I don’t think I’m going to get the SK III as I first thought and have been kinda eyeing the BlackBerry Pearl.

First, let me say, if you’re tired of reading about the iPhone then just skip this entry altogether. These are my personal thoughts on why I won’t buy it, if you don’t care that’s perfectly fine.

Some of you who know me are probably a little surprised that I wouldn’t even consider buying an iPhone. I’ve owned a SideKick 2 for the past 2 or 3 years and really like it alot. I use it when I go back and forth to class browsing some of my favorite blogs and use SMS/Chat to send short messages to friends. When I first saw the iPhone I thought “Damn! Apple has really done the UI right, finally.”

So, why won’t I buy an iPhone?

A lot of the questions that have been coming out are now somewhat answered by David Pogue’s Ultimate iPhone FAQ. I’ll highlight the ones that are Nos that until they are turned to Yeses mean I will not be buying one anytime soon.

Can it be used with anything but Cingular? –No.

I’m sorry but this really irritates me. I’m locked into T-Mobile because Danger has an exclusive deal with them and that pisses me off. Plus I’ve heard nothing but extremely bad things about Cingular since they “merged” with AT&T (they sucked when I was on them before).

Will there be a non-Cingular version? –Not within the first two years.

This just tells me that Apple is playing the Cell providers game and not setting the playing field themselves as they have in the past (read iTunes Store).

Can it run Mac OS X programs? –No.

Mildly irritating, but definitely understandable.

Can I add new programs to it? –No. Apple wants to control the look and feel and behavior of every aspect of the phone.

This is the biggie for me, this is like buying a computer with software that only Apple provides. It’s like them telling me to shut up and like it, well I don’t. This also means that I can’t develop for it which irritates me to no end.

Does it connect to iChat? –No.

Whaaat?!!?

Does it have games? –No.

See previous entry.

Does it have GPS? –No.

Again, WTF?! Come on every new phone out there now (at least that I know of) has this. Come on Apple!

Voice recognition? Voice dialing? Voice memos? –No, although this could change by June when the phone ships.

Ok, if you aren’t going to give me freakin’ buttons to dial with then make it easier to dial.

Does the Web browser support Flash or Java? –No.

I understand the Java part, but no Flash stuff, grrr.
On this note, there is nothing that says this won’t do JME (Java Micro Edition) stuff.

Can you change the battery yourself? –No. You’ll have to send the phone in to Apple for battery replacement, just as with the iPods.

Ok, I’ve had 3 cell phones batteries go out on me on previous phones and have been able to replace them. However, I just noticed on my SideKick 2 that I cannot change the battery on this one very easy either. So, hrmmm, oh well.

Now that I’m looking at phones again (specifically ones for T-Mobile) I’m not sure what I’m going to do. I originally thought I’d go with the SideKick III, but after seeing the iPhone I want something with a much better (and bigger) screen and a freakin’ decent web-browser. Just FYI here’s what I use my SK II for: browsing blogs, text messaging, and occasionally sending an e-mail of a link or something interesting (and calling of course).

Also, just noticed an update to the FAQ, good read and some more disappointing answers. I don’t know, I think when it comes down to it I’m going to wait until the iPhone 2.0 comes out and they “fix” some of my gripes, or someone will have come out with a phone that I really like (unfortunately the iPhone is the closest anyone has come since my SK II).

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Easy AdSense by Unreal