I Like My Method Pointers With Curry in Groovy
Invoking a method several times can easily be done in Java in a loop. But what if we have several methods that need to be executed several times? Since Java does not feature pointers to functions, we cannot pass functions around, and cannot create a generic method that takes a pointer to a method and executes it. This is where Groovy shines.
Suppose we want to check on the status of some external system or work. We want to check the status every half a second for a maximum of ten times in total.
// the generic type in Closure<Boolean> indicates its return type
boolean isOperationSuccessful(int numOfTries, Closure<Boolean> action) {
Thread.sleep(500)
for (i in 0..<numOfTries) {
if (action()) {
return true
} else {
Thread.sleep(500)
}
}
}
// we can pass closures...
def check = { int n -> new Random().nextInt(10) == n }
println isOperationSuccessful(10, check.curry(3))
// ... as well as methods
boolean isWorkDone(int id) {
// check if particular external system identified by `id` is done
return new Random().nextInt(2) == 1
}
// `.&` is the method pointer operator
println isOperationSuccessful(5, this.&isWorkDone.curry(1))
We can pass methods around by referencing them with the method pointer
operator
.&
:
def pointerToUpper = 'hello world'.&toUpperCase
assert pointerToUpper() == 'HELLO WORLD'
By using Groovy’s take on currying, we can fix parameters of a closure (or method):
def power(double n, int exponent) { n ** exponent }
def squared = this.&power.rcurry(2)
assert squared(12) == 144
rcurry
fixes the right-most argument of the method, curry
the
left-most. (And yes, there is also an index-based method: ncurry
).
Both return a new Closure
that takes one less argument.