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.

Leave a Reply

Your email address will not be published. Required fields are marked *