Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke method as closure

My understanding of the Groovy operator .& is that it converts a method call to a closure. Therefore it seems like the following code (which can be run in the Groovy console) should work:

class Foo {
  def method(def param) {
    param + 10
  }
}

def invokeClosure = {Closure closure ->
   return closure.call()
}

def f = new Foo()
invokeClosure f.&method(6)

Of course if I change the last line to

invokeClosure {f.method(6)}

it works fine, but what's wrong with my understanding of the .& operator?

Thanks, Don

like image 206
Dónal Avatar asked Sep 08 '09 17:09

Dónal


2 Answers

When converting a method to a closure using .& notation you leave off the parameters. f.&method(6) is the same as calling f.method(6) which will return 16, so in your example you are passing 16 into invokeClosure and not a closure. Which causes the following exception since the Integer class doesn't have a call method:

Exception thrown: No signature of method: java.lang.Integer.call()

Below passes a method pointer for f.method into invokeClosure and would be how you would typically use .&.

class Foo {
  def method(def param) {
    param + 10
  }
}

def invokeClosure = {Closure closure ->
   return closure.call(6) // can leave off .call
}

def f = new Foo()
invokeClosure f.&method

As you pointed out the following will work:

invokeClosure {f.method(6)}

That's because you are passing a closure that takes no parameters so that's why closure.call() works in that case.

like image 189
John Wagenleitner Avatar answered Sep 28 '22 09:09

John Wagenleitner


Use invokeClosure f.&method.curry(6) instead. This is a closure which could be called without parameters

like image 36
Manuel Avatar answered Sep 28 '22 10:09

Manuel