Posterous theme by Cory Watilo

Filed under: groovy

Higher-order functions with Groovy

I'll admit, higher-order functions sounds like link bait for over-achievers. Trust me, I didn't invent the term :-) A Higher-order function is a concept from mathematics where a function accepts other functions as its arguments, and can return functions as results.

Higher-order functions are related to functional programming but higher-order functions != functional programming. In computer science higher-order functions consists of two things: closures and currying. Groovy supports both :-)

So what's a closure then? Closures are not unique to Groovy. Ruby, Lisp, JavaScript and D have closures as do many other languages.

A closure in Groovy is three things:

  1. a block of code that can access variables in the scope where it is declared.
  2. a function that can take arguments and always returns a result (may be null)
  3. an object that has properties and methods with and without side-effects

Calling a closure if thread-safe if the implementation is thread-safe. Here's an example of a closure:

1.def x = { println it }

And here's how you call it (two options):

1.x('Hello, world!')
2.x.call('Hello, world')

Closures can take arguments, including other closures:

1.def isList = { i -> i instanceof List }
2.if (isList([])) {
3.    println "This is a List"
4.}

Closure arguments can be typed:

1.def prefix = {
2.    String s ->
3.    while (s.length() < 17) {
4.        s = "0$s"
5.    }
6.    s // return keyword is not required
7.}
8.def id = prefix "1234" // parentheses are not required

Closures can be passed as arguments, for example to the each() method on java.util.Map:

1.System.properties.each { println it }

And a closure can call itself recursively:

1.// Thanks to Sergey Bondarenko for this one-liner
2.def fac = { int i -> i == 1 ? 1 : i * call(i - 1) }
3.println fac(10) // parentheses are required for fac since I call println without

Closures can access the variables in the scope where they are declared:

1.def pi = 22 / 3
2.def calcSurface = { radius -> pi * (radius * radius) }
3.def surface = calcSurface 10

Currying is closely related to closures. With curring you can construct programs by appending argument values to closures:

01.def appendForLength = {
02.    int length, String charachter, String toBeAppended ->
03. 
04.    while (toBeAppended.length() < length) {
05.        toBeAppended = "${character}${toBeAppended}"
06.    }
07.    return toBeAppended
08.}
09.def myKindOfId = appendForLength.curry 17, "0"
10.assert "00000000000012345" == myKindOfId("12345")

The call to the curry() method on line 9 passes two arguments to the appendForLength closure and returns a new closure. This new closure takes one argument which is actually the third argument of the appendForLength closure.

And with currying you can go beyond Groovy closures, you can also curry any Java method. First you need to know how to turn a method into a closure. You add the ampersand (&) character in front of the method name:

1.def getProperty = System.&getProperty

The value that is returned is a closure:

1.def getProperty = System.&getProperty
2.getProperty("java.version")

And since it's a closure you can curry it:

1.def getProperty = System.&getProperty
2.def javaVersion = getProperty.curry("java.version")
3.assert "1.5.0_04" == javaVersion()

Higher-order functions simplify programs. It's closely related to functional programming. You've learned how to convert regular Java methods to higher-order functions. You can also do the inverse: convert higher-order functions to Java interface methods. This and other techniques will be the subject of the second installment.

Update: part two has been posted too. Happy coding!
0

Average: 3.8 (6 votes)

Nice three-part series on higher-order function (read: closures) from Steven Devijver over on DZone. Gives a nice explanation of currying (including an interesting example of currying Java methods), and one of the clearest explanations of closure delegates I've read. Definitely worth a read!

Groovy goodness: force synchronized access to non-synchronized method with metaprogramming

Say you’ve got a singleton instance of some class to which you’d like to enforce synchronized access. No need for sub-classing, proxies or related tomfoolery with Groovy: just hack that metaclass!

Enforce synchronized access to all methods of a single instance
def resource = FactoryClass.getSingleton()
def lock = new ReentrantLock()
resource.metaClass.invokeMethod = { String name, args ->
    def result
    def metaMethod = delegate.metaClass.getMetaMethod(name, args)
    if (metaMethod) {
        lock.lock()
        try { result = metaMethod.doMethodInvoke(delegate, args) }
        finally { lock.unlock() }
    } else {
        throw new MissingMethodException(name, delegate.class, args)
    }
    return result
}

// ... and later, from multiple threads ...
resource.doSomething() // <- call will be synchronized

Get the latest mongodb cheatsheet straight to your terminal

I've been really getting into the mongodb document-oriented database recently.  For those of you yet to join the NoSQL party, mongodb is a fast, easy to use JSON-based document store.  For a nice, quick overview, check out this slideshow:

The mongodb command set isn't huge, but it's always useful to have a cheatsheet to hand when you're learning a new technology.  I found the one at http://cheat.errtheblog.com/s/mongo to be pretty good.  I thought about saving it to a text file for easy access when working in a terminal - then I noticed that the author has been refreshing the cheatsheet as mongodb matures and the command-set changes.  Now, an out-of-date cheat-sheet isn't much good, so I thought I'd knock together a quick shell script to deliver the latest version to my terminal.

The script is implemented using curl and a Groovy one-liner. The wonderful @Grab annotation is great for this kind of thing - I've built up a bunch of Perl one-liners like this over the years, but I'm starting to discover that Groovy trumps Perl for many little text-processing jobs like this.

Append this line to your .bashc script, then the next time you can't quite remember the syntax of a mongodb command, simply enter mongocheat | less

(Note: The first time you run this, it'll probably take a while, since Groovy may have to download the NekoHTML libraries.  Subsequent executions will be much faster!)

Groovy gotcha: Equality operator uses compareTo() rather than equals() for Comparable classes

For the most part I love the expressiveness and conciseness of Groovy when compared to Java.  Most days I really enjoy writing Groovy code, and love the productivity boost that comes from not having to write and test so much boilerplatery.  However, other days Groovy can feel a little flaky, and I miss the predictability of good old Java.  More importantly, with Groovy you will occasionally come across some pretty obscure behaviour which leaves you scouring Nabble and JIRA for solutions.

Case in point: when new to Groovy, one of the first things you will learn is that while in Java the == operator test for object identity, in Groovy the same operator tests for object equality, using the equals() method of the object to the left of the operator. (In Groovy, object identity is tested using the is() method).  So far, so good.  However, what you might not learn is that if the object on the left of the == operator implements the Comparable interface, the == operator will test for equality by calling compareTo() == 0.

It's very easy to get tripped up by this, especially if you have overridden the equals() method:

The solution, in cases like these, is to either a) ensure that x.compareTo(y) returns 0 in all cases where x.equals(y) would return true (or vice-versa), or b) remember to use x.equals(y) instead of x == y, whenever the class of x implements Comparable.

Personally, I feel the principle of least surprise applies here, and the == operator should always call equals().  However, I'm aware that there are no doubt some cases (particularly where other comparisons such as <, >, <= and >= are being used) where the principle of least surprise would dictate that the current behaviour is preferable.

If you have strong arguments either way, I'd be interested to hear them in the comments.