How to call a Groovy Closure with an Object Array - groovy

I may be misunderstanding how to use varargs, but according to the Groovy Docs for Closures, for the function public V call(Object... args) , the arguments parameter "could be a single value or a List of values".
But when I try to do something like this:
Closure myClosure = { arg1, arg2, arg3 ->
println arg1 == null
println arg2 == null
println arg3 == null
}
Object[] argsArray = new Object[]{"John", "Jack", "Mack"}
myClosure.call(argsArray)
The compiler throws an groovy.lang.MissingMethodException: No signature of method: .call() is applicable for argument types: ([Ljava.lang.Object;)
I couldn't even get the varargs function to work when passing in an actual varargs either.
def myVarargsFunction(Object... args){
println "myVarargsFunction"
myClosure.call(args)
}
This code results in the same error (After I change the scope of Closure myClosure of course).
I don't under stand why either or these situations do not work. I know there are other ways to get this to work, I just want to understand why this doesn't work.

You can use the spread operator:
myClosure.call(*args)

Related

how to use closure for passing multiple argument in closure in groovy

below is my groovy code I want to pass multiple arguments in closure in groovy
package com.test.demo
def str = {'Yash' , 'deep'}
def merged = { println "$str world"}
merged.call()
this code is giving me an error please anyone give me a solution how can I pass multiple arguments in closure in groovy
There are two problems with your original code:
{ 'Yash' , 'deep' } does not imply returning an array, but this will
give you an error:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/tmp/x.groovy: 2: Unexpected input: ',' # line 2, column 19.
def str = {'Yash' , 'deep'}
So you have to rewrite that closure to:
{['Yash' , 'deep']}
(note the [])
Next, if you print the closure like this, you would get the reference
printed - so you need to call it.
def merged = { println "${it()} world"}
def str = {['Yash' , 'deep']}
merged(str)

Get Parameter list of a closure dynamically in Groovy

I have a Closure defined in a groovy file that load with the shell.evaluate() method.
I need to call this closure in by calling program using the shell."$closurename".call(arguments) call.
However to formulate the closure parameters ( argument above) I'd need to now what are the arguments and arguments names that the closure $Closurename accepts. Is there a way of dynamically knowing this in Groovy? I checked in the metaClass.method property but this does not work in my example below.
Below is the example code.
def arguments;
shell.evaluate(new File("/tmp/myGroovyClosureFile.groovy"))
testBlock = "myClosureName"
//Code here to find the parameters for myClosureName and create
//the arguments variable
shell."$testBlock".call(arguments)
As Jeff mentioned, it seems like groovy when generating code for closures anonymizes somehow the parameter names. However, you can still use reflection to get as much information as you can:
def cl = { int a, String b ->
println(a)
println(b)
}
def callMethod = cl.class.methods.find {
it.name == "call"
}
println callMethod.parameterTypes
println callMethod.parameters.name
and outputs:
[int, class java.lang.String]
[arg0, arg1]
Is there a way of dynamically knowing this in Groovy?
You can't really do it dynamically at runtime.

In the below code function is returning value of variable a, how is it possible, please explain

In the below code function myprint is returning value of variable a, how is it possible, please explain
class Test {
def myprint(){
def a = "my"
}
}
def test1 = new Test()
log.info test1.myprint()
You're encountering a groovy method without return statement.
Indeed, as stated in Groovy Goodness, as an example, the return statement is not mandatory to end a Groovy method : the result of the last executed instruction is used asmethod return value.
As a consequence, writing
def myMethod() {
def a = "value"
}
println myMethod()
will output
value
Because Groovy interpreter will consider def a = "value" as last instruction to be method return value.
However, for clarity reasons, and contrary to groovy commitee, I will suggest you not to use that feature, as it make code a little less readable.
Bonus point : this feature really goes well with closures : when calling [1,2,3].collect { it*2} will return [2, 4, 6] which is really nice.

Using `evaluate` function. Why it doesn't work?

This code:
evaluate ("def test() { println \"Test is successful!\" }")
test()
results in exception:
FATAL: No signature of method: script1409644336796288198097.test() is applicable for argument types: () values: []
Possible solutions: use([Ljava.lang.Object;), getAt(java.lang.String), use(java.util.List, groovy.lang.Closure), use(java.lang.Class, groovy.lang.Closure), wait(), wait(long)
groovy.lang.MissingMethodException: No signature of method: script1409644336796288198097.test() is applicable for argument types: () values: []
Possible solutions: use([Ljava.lang.Object;), getAt(java.lang.String), use(java.util.List, groovy.lang.Closure), use(java.lang.Class, groovy.lang.Closure), wait(), wait(long)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
...
What I'm doing wrong?
That script evaluation results in null. You should either return something or execute the script and return the result.
An example returning a closure instead of defining a method:
test = evaluate ('return { "Test is successful!" }')
assert test() == "Test is successful!"
And an example where the script executes the method itself:
result = evaluate 'def test() { "eval test" }; return test()'
assert result == "eval test"
If you cannot change the script code, you may parse a class from the script, create a new object, and then execute the test() method:
def parent = getClass().getClassLoader()
def loader = new GroovyClassLoader(parent)
def clazz = loader.parseClass('def test() { "new class definition" }');
obj = clazz.newInstance()
assert obj.test() == "new class definition"
If a variable has an undeclared type, then it goes into the script binding. The binding is visible to all methods which means data is shared.
evaluate() is a helper method to allow the dynamic evaluation of groovy expressions using this scripts binding as the variable scope.
In a variable binding, you can declare a closure which accepts no argument and must be restricted to calls without arguments.
With all of that in mind, here is your script working as intended.
evaluate ("test = { -> println \"Test is successful!\" }")
test()
You can do this using the ExpandoMetaClass to add dynamic closures to your own class. You would need to parse the string beforehand to split it into function name, arguments and code.
methodName = "test"
methodArgs = []
methodCode = """println "Hello World!" """
this.metaClass."$methodName"{ code, args ->
evaluate(code)
}
Then you can call it by doing:
"$methodName"(code, arguments)
or
test(code, arguments)
To get the output Hello World!
You can read more about ExpandoMetaClass here http://groovy.codehaus.org/ExpandoMetaClass
In addition to all other answers, if you don't want to change the structure of your code you can simply use return this at the end of your groovy-string:
lib = evaluate ("def test() { println \"Test is successful!\" }; return this")
lib.test()

Groovy unusual convention

I have seen strange code for many times:
...
private currencyFormat = NumberFormat.currencyInstance
def convert = currencyFormat.&parse
...
By strange I mean this -> .&parse. Why logical AND operator is needed and who else it can be used?
That's a method pointer
convert is now effectively a Closure which delegates to the parse method
Example
It's defined here without an example, and mrhaki did a post about it here.
And as an example showing it handles overloading, consider a class with 2 static methods:
class Test {
static void printSomething( String thing ) {
println "A:$thing"
}
static void printSomething( String thing, String thing2 ) {
println "B:$thing$thing2"
}
}
We can get a reference to the printSomething methods:
def ref = Test.&printSomething
And then we can pass it to an each call on a list of single items:
// prints A:a and A:b
[ 'a', 'b' ].each ref
Or we can pass it two items and it will pick the correct overloaded method to call:
// prints B:ab and B:cd
[ [ 'a', 'b' ], [ 'c', 'd' ] ].each ref
It's not a bit manipulation operator. The ampersand was probably chosen because that's what C's address operator uses. The idea is that you can pass around references to a method on a specific instance.
Say you have some logic like:
def stuff = null
if (condition) {
stuff = foo.doThis(a, b, c)
} else {
stuff = bar.doOther(a, b, c)
}
You can rewrite that with a method pointer like this:
def myMethod = condition ? foo.&doThis : bar.&doOther
def stuff = myMethod(a, b, c)
It doesn't mean and. It's special syntax to reuse a method as a closure. Now you can use convert in places where you can pass a closure, like grep, find or similar methods.

Resources