Archive

Posts Tagged ‘currying’

Chain those Crazy Groovy Closures with Currying, Case Study: Mimicking Intercepting Filter

November 3, 2008 Peabody 7 comments
Below is a post I wrote a little while back but never published. If you’re wanting to learn better how closures work or how to use currying, this can be a really fun exercise. I didn’t publish this earlier because I didn’t want to encourage anyone to implement this in production code as if this were some kind of pattern.
 
Please, treat this post merely as something fun to play with. Do not use this in production code. Please, I beg you. Think of the kittens.
- Peabody
———————————————
A week ago Josh and I wanted to chain a bunch of behaviors together in Groovy.
 
One of the first possible solutions that popped to mind was the very flexible Intercepting Filter pattern common to Java EE web applications.
 
I think we ended up deciding, for what we actually needed, this neato solution wasn’t the best fit. But the process was extremely rewarding and sharing it might help some folks get a better feel for how powerful closures can be and get a little more familiar with currying.
 
Here’s the basic pattern diagram for the Intercepting Filter from Sun’s site. The important parts here are the Filters One, Two, and Three. We want to be able to call a chain of these filters and each filter will be responsible for doing any pre or post processing and likely call the next filter in the chain at some point in the middle.
 
Figure 7.1
Here are our three filters. They’re simply closures that accept another closure as an argument. In JavaEE, the Intercepting Filter gets added to a chain of other filters. Each one can run some pre-processing logic, call the next item in the chain, then call some post-processing logic before returning. In our closures, the pre and post processing both simply output something to the console and, in between those, we call the next item in line with c.call(). The c={} argument defaults our c variable to an empty closure if no other closure is passed in as an argument. 

def one = { c={}->
  println "one*";    c.call();  println "*one"
}
def two = { c={}->
  println "two*";    c.call();  println "*two"
}
def three = { c={}->
  println "three*";  c.call();  println "*three"
}

Note to Reader: Please copy this code into your GroovyConsole as you follow along. It will be much, much more fun for you that way. ;)
 
So now I can call one of my fancy new closures like I would a method.
Try this:
two()
Output:
two*
*two
 
I called the two closure with no parameters. This worked even though the signature for two has an expected variable of c. It did not complain because I declared it c={} which means that it will just default to an empty closure if I don’t supply one.
 
Let’s call our two closure again now but supply it with another closure as an argument.
Try this:
two{ println ‘hey there!’ }
Output:
two*
hey there!
*two
 
That worked pretty well. Now let’s try combining the closures.
Try this:
one{two{three()}}
Output:
one*
two*
three*
*three
*two
*one
 
That’s pretty sweet. But we might end up needing a handful of behaviors to run through and that curly brace syntax can become messy quickly.
 
We know that with a little currying we can build all of my little closures into a bigger closure.
def myChain = one.curry(two.curry(three.curry({})))
Then we can call that one chain by itself.
myChain()
 
But we want to dynamically build that chain. We should be able to call it like:
chain([one, two, three])
Or if we had more closures:
chain([one,two,three,fo,get,yo,wo,man,on,tha,flo])
 
That allows us to pack a lot of behavior into a small amount of code and we can mix, match, and put these behaviors in any order we want.
 
Here’s a little method to help us with that.
def chain(List commands){
  def chainToCall = {}
  commands.reverse().each{command->
    chainToCall = command.curry(chainToCall)
  }
  chainToCall()
}
 
Give it a try! :)
 
PS – Here is an even shorter version of that chain method by using inject. One of my next posts to Inside the Machine will explain inject in greater detail. I hope you can see that inject allows much more succinct code.
def chain(List commands){
  commands.reverse().inject({}){chainToCall, command->
    command.curry(chainToCall)
  }()
}
Categories: Groovy Tags: , ,