views:

79

answers:

1

Hi,

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

+2  A: 

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.

John Wagenleitner
Actually, strictly speaking I think `{f.method(6)}` is a closure that takes one parameter whereas `{-> f.method(6)}` is a closure that takes no params. Great answer though, thanks!
Don