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

Processing (the language) as a DSL

Posted by Warner Onstine on December 09, 2006

I first read about Processing in an old Wired issue (wow, finally found it, do you know how hard it is to search on “processing” on the Web? Uggh). When I first found Processing I wasn’t even thinking about DSLs (this was 3 years ago), but I know that one of my first thoughts was “Why not just use Java directly?”, but now I definitely see the light. I’ve been following the amazing work that others have been doing with Processing who have very little Java programming experience, but they know 2d and 3d graphics.

The cool thing is, is that while Processing is a DSL it is built on top of Java and can leverage any of the packages that Java has (much like Groovy can) which leads to some very interesting hardware projects. And of course, I’m also interested in Processing because I love 2d and 3d graphics and finding interesting ways to interact with them.

In short, I guess, I just wanted to point out that DSLs are everywhere, even if we didn’t see them at first, they aren’t a new idea, they’ve just been given power by naming them (much in the way that Ajax was).

Anyone have some other interesting DSLs that they’ve found?

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

Groovy as a DSL

Posted by Warner Onstine on December 09, 2006

Guillame Laforge (one of the Groovy programmers) posted his thoughts on using Groovy as a DSL.

With the help of closures, methods, operator overloading, adding
properties & methods to classes, with named parameters and so on, you
can quickly come up with a language of your own, a DSL, targeted at
the subject you’re dealing with.

This was in response to an article that ran on Artima “Creating DSLs with Ruby”, of which most of the examples could be easily modified to Groovy code.

The Groovy team has created a page, “Writing Domain-Specific Languages”, to showcase some of the examples of using Groovy as a DSL, which I will probably be committing more to as the Chama project continues.

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

New project “Chama”

Posted by Warner Onstine on December 07, 2006

So, where has all this DSL stuff been leading? One of my projects that has been sitting on the back-burner for a while has been Chama. Chama was born out of the frustration of writing the same boiler-plate code over and over for database-backed sites that are run on Tapestry. While you can certainly use something like Trails I was not happy with the additional amount of configuration I needed to do in order to get the forms to look and behave the way I wanted them to.

Why not use Ruby on Rails then, or even Grails if I want to stick with the Java theme?

A variety of reasons:

  • I’m familiar with Tapestry, Hibernate, etc.
  • I’m very familiar with Java
  • I want to learn Groovy as a language
  • I don’t want to switch out my deployment options to have to deal with deploying my apps to a new server and having to configure it all over again so that it’ll run RoR
  • I like generators ;-) , no really this is an exercise that I want to undertake and if others find value in it that’s great
  • Mostly to make it easier for me to get some app ideas I’ve had off of the ground

What will Chama use:

  • Groovy as the primary language, with some Java thrown in where needed
  • Most likely Yaml for configuration with JYaml for dealing with it
  • Quite possibly several DSLs for each area (Model, View, Controller)

I don’t know yet exactly how far I’m going to take Chama, mostly I just want to get a tool together that will help me build stuff. If others find value in it and it gets extended from there and heads in a direction I never thought about, great! All the code will be available under an Apache License once I start working on stuff. I have some tentative dates setup in my Trac instance (what?! using Python for a Java app?). Comments are welcome, and I will use this blog to announce releases as they happen, the first milestone is set for 12/22/06 (oops was tomorrow, moving to two weeks, wow it’s been two weeks since I first set this up already).

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

DSLs

Posted by Warner Onstine on November 27, 2006

I’ve been interested in languages ever since I was little and I first learned how to read. I’ve taken French in High School and German in college, I just love being able to find similarities and difference in languages (one of the reasons I’m toying with taking some linguistics classes for my upper-division credits). I also really love programming languages, for some reason I actually bought a book on Modula-2 just based on an article I read on Dr. Dobb’s Journal waaaay back when. In my short time as a programmer I’ve looked at PostScript, Objective-C, Smalltalk (just a little), Java, C, Ruby, Groovy, etc. if it seemed at all interesting I picked it up and shook it to see what fell out.

This summer I went to NFJS (No Fluff Just Stuff) in Phoenix and got to hear Neal Ford talk about Domain Specific Languages (DSLs for short). He went through a number of examples of how to do a DSL inside of a language like Ruby, or Java and also talked about Lisp and how after a time you rose above the language and were in a domain-space.

I listened to this raptly and began to understand where some of my earlier research had led me. A few years ago I picked up a book called Generative Programming, which actually talked about some of the same technologies that Neal was talking about now. Of course to me alot of the book was over my head, but still very interesting. I think that we are now in this space, there is no magic bullet to solve every project, and if the domain is big enough you should be writing something “in that domain” not in Java, Struts, Tapestry, etc. Those are the tools you use when you deploy, but not when you write an app for your domain.

This is what RoR gets, this is what RoR is about, it is about a tool that will help you build an app for a domain. I think in the next year or so we are going to see alot of DSLs pop up that work on very specific domains, or allow you to tweak, and add-on to change for your domain.

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

More Parsing Fun 1

Posted by Warner Onstine on November 27, 2006

Since I’ve started thinking about DSLs I’ve picked up another book on my bookshelf Building Parsers with Java and leafing through it looking at how to actually build up a variety of languages using Java. As I was browsing through my Groovy user list I came upon a link to an active Java Parser called JParsec.

JParsec definitely looks interesting and they even have a Groovy extension that looks pretty slick.

Another interesting item that showed up in the Building Parsers book has to do with how he splits up language types. He defines them in the following way:

  • Data language – this language is one that when parsed creates objects. Should be familiar to most, essentially most XML documents can be parked right here, or any kind of configuration like YAML.
  • Logic language – this language that when parsed executes logic statements, helps to define the relationship between objects, such as business rules. Languages like Curry fall in this camp.
  • Query language – this language provides the ability to query some kind of store, includes SQL, XPath, XQuery, etc.
  • Expression language – this language consists of values, variables, operators and functions (often in a small and concise manner) that when executed yields a result. Regex and OGNL fall into this camp.
  • Imperative language – A full blown language like Ruby or Java
  • Engines – These are used by query and logic languages to interface with the data store or look through a variety of values and rules that might be needed by the logic language to execute its statements.
Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Easy AdSense by Unreal