In Groovy, how to get annotation values for parameters inside closures? - groovy

For example, given this groovy code:
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.ElementType
import java.lang.annotation.Target
#Target([ElementType.PARAMETER])
#Retention(RetentionPolicy.RUNTIME)
#interface Bar {
String qux() default ""
}
def closure1 = { #Bar(qux = 'zxv') String foo ->
println foo
}
println "[value for qux]"
How would you print the value for qux (which in this case is 'zxv') ?

Reflection API can give you what you're looking for (I'm using Groovy 2.5 on Java 8).
The closure is essentially a method named call on a Closure instance, and parameterAnnotations[0][0] is a quick way of getting that method's first parameter's first annotation.
def anno = closure1.class.methods.find { it.name == 'call' }.parameterAnnotations[0][0]
println anno.qux() // prints zxv

Related

Finding list/map of free variable(s) of a closure in groovy

This is my simple groovy script;
def fourtify(String str) {
def clsr = {
str*4
}
return clsr
}
def c = fourtify("aa")
println("binding variables: ${c.getBinding().getVariables()}")
...
All I'm trying to do here is being able to access the free variable "str" using the closure instance to understand how closure works behind the scenes a bit more better. Like, perhaps, Python's locals() method.
Is there a way to do this?
The closure you have defined does not store anything in binding object - it simply returns String passed as str variable, repeated 4 times.
This binding object stores all variables that were defined without specifying their types or using def keyword. It is done via Groovy metaprogramming feature (getProperty and setProperty methods to be more specific). So when you define a variable s like:
def clsr = {
s = str*4
return s
}
then this closure will create a binding with key s and value evaluated from expression str * 4. This binding object is nothing else than a map that is accessed via getProperty and setProperty method. So when Groovy executes s = str * 4 it calls setProperty('s', str * 4) because variable/property s is not defined. If we make a slightly simple change like:
def clsr = {
def s = str*4 // or String s = str * 4
return s
}
then binding s won't be created, because setProperty method does not get executed.
Another comment to your example. If you want to see anything in binding object, you need to call returned closure. In example you have shown above the closure gets returned, but it never gets called. If you do:
def c = fourtify("aa")
c.call()
println("binding variables: ${c.getBinding().getVariables()}")
then your closure gets called and binding object will contain bindings (if any set). Now, if you modify your example to something like this:
def fourtify(String str) {
def clsr = {
def n = 4 // it does not get stored as binding
s = str * n
return s
}
return clsr
}
def c = fourtify("aa")
c.call()
println("binding variables: ${c.getBinding().getVariables()}")
you will see following output in return:
binding variables: [args:[], s:aaaaaaaa]
Hope it helps.
in your example str is a parameter of the method/function fortify
however maybe following example will give you better Closure understanding:
def c={ String s,int x-> return s*x }
println( c.getClass().getSuperclass() ) // groovy.lang.Closure
println( c.getMaximumNumberOfParameters() ) // 2
println( c.getParameterTypes() ) // [class java.lang.String, int]
the locals() Python's function better matches groovy.lang.Script.getBinding()
and here is a simple example with script:
Script scr = new GroovyShell().parse('''
println this.getBinding().getVariables() // print "s" and "x"
z = s*(x+1) // declare a new script-level var "z"
println this.getBinding().getVariables() // print "s", "x", and "z"
return s*x
''')
scr.setBinding( new Binding([
"s":"ab",
"x":4
]) )
println scr.run() // abababab
println scr.getBinding().getVariables() // print "s", "x", and "z"

Object definition or method call?

In the documentation/section 14.4 I came accross with the following example of code:
task configure << {
def pos = configure(new java.text.FieldPosition(10)) {
beginIndex = 1
endIndex = 5
}
println pos.beginIndex
println pos.endIndex
}
It's not quite clear what the pos and the configure means. I thought configure is just a property, so we can write something like
println configure.beginIndex
but the line causes compile-time error. And
{
beginIndex = 1
endIndex = 5
}
is just a closure, is it?
configure() is a method of the gradle Project object. The documentation of this method explains what it does:
Object configure(Object object, Closure configureClosure)
Configures an object via a closure, with the closure's delegate set to the supplied object. This way you don't have to specify the context of a configuration statement multiple times.
Instead of:
MyType myType = new MyType()
myType.doThis()
myType.doThat()
you can do:
MyType myType = configure(new MyType()) {
doThis()
doThat()
}
So the manual snippet defines an object of type FieldPosition, assigns it to the variable pos, sets its beginIndex and endIndex properties using a closure, thanks to the configure() method of Project, and then prints these properties.
It's a pointless example showing how to use the gradle DSL to configure several properties of an object.

Trouble "overriding" values in a Groovy closure with .delegate

I'd like to call a closure with a delegate parameter to override or shadow the calling context. But the following example prints prints "outside" where I expect "inside".
What am I doing wrong?
def f(String a){
def v = { return a }
v.delegate = [a:"inside"]
// Makes no difference:
// v.resolveStrategy = Closure.DELEGATE_FIRST
println(v.call())
}
f("outside")
I believe the issue is that when the closure is declared inside the function, it 'closes' round the known values in the method (a), so that value becomes effectively hard-coded into the closure (it never hits the delegate to find the unknown value as it is known to the Closure).
If you move the closure v definition outside of the function f, then it works:
v = { return a }
def f(String a){
v.delegate = [a:"inside"]
println(v.call())
}
f("outside")
Other option is to use getProperty('a') instead of directly using a as this forces the use of the delegate to retrieve the value of a.
Can also be done by referring the delegate in the closure. For v as a closure, a does not make any sense (equivalent to use of ExpandoMetaClass)
def f(String a){
def v = { delegate.a }
v.delegate = [a:"inside"]
println v()
}
f("outside")

In order for a groovy closure to modify a variable defined in the scope of a delegate, do you need to explicitly specify delegate.theVariableName?

I stumbled onto something with Groovy closures and delegates that I'm not sure is an official part of the language or perhaps even a bug.
Basically I am defining a closure that I read in as a string from an external source,
and one of the variables in the class that defines the closure needs to be modified by the closure. I wrote
a simple example showing what I found works, and what does not work.
If you look at the test code below you will see a class that defines a variable
animal = "cat"
and two closures defined on the fly from strings that attempt to modify the animal variable.
This works >
String code = "{ -> delegate.animal = 'bear'; return name + 'xx' ; }"
But this does not
String code = "{ -> animal = 'bear'; return name + 'xx' ; }"
It seems like I need to explicitly qualify my to-be-modified variable with 'delegate.' for this to work.
(I guess i can also define a setter in the enclosing class for the closure to call to modify the value.)
So.... I've found out how to make this work, but I'd be interested if someone could point me to some groovy
doc that explains the rules behind this.
Specifically.... why will the simple assignment
animal = 'bear'
affect the original variable ? Are there shadow copies being made here or something ?
import org.junit.Test
/*
* Author: cbedford
* Date: 8/30/12
* Time: 1:16 PM
*/
class GroovyTest {
String animal = "cat"
String name = "fred"
#Test
public void testDelegateWithModificationOfDelegateVariable() {
String code = "{ -> delegate.animal = 'bear'; return name + 'xx' ; }"
def shell = new GroovyShell()
def closure = shell.evaluate(code)
closure.delegate = this
def result = closure()
println "result is $result"
println "animal is $animal"
assert animal == 'bear'
assert result == 'fredxx'
}
// This test will FAIL.
#Test
public void testDelegateWithFailedModificationOfDelegateVariable() {
String code = "{ -> animal = 'bear'; return name + 'xx' ; }"
def shell = new GroovyShell()
def closure = shell.evaluate(code)
closure.delegate = this
def result = closure()
println "result is $result"
println "animal is $animal"
assert animal == 'bear'
assert result == 'fredxx'
}
}
Groovy closures have five strategies for resolving symbols inside closures:
OWNER_FIRST: the owner (where the closure is defined) is checked first, then the delegate
OWNER_ONLY: the owner is checked, the delegate is only checked if referenced explicitly
DELEGATE_FIRST: the delegate is checked first, then the owner
DELEGATE_ONLY: the delegate is checked first, the owner is only checked if referenced explicitly
TO_SELF: neither delegate nor owner are checked
The default is OWNER_FIRST. Since the closure is defined dynamically, your owner is a Script object which has special rules itself. Writing animal = 'bear' in a Script will actually create a new binding called animal and assign 'bear' to it.
You can fix your tests to work without explicitly referencing delegate by simply changing the resolve strategy on the closure before calling it with:
closure.resolveStrategy = Closure.DELEGATE_FIRST
This will avoid the odd the Script binding and use the delegate as expected.

How do I create and access the global variables in Groovy?

I need to store a value in a variable in one method and then I need to use that value from that variable in another method or closure. How can I share this value?
In a Groovy script the scoping can be different than expected. That is because a Groovy script in itself is a class with a method that will run the code, but that is all done runtime. We can define a variable to be scoped to the script by either omitting the type definition or in Groovy 1.8 we can add the #Field annotation.
import groovy.transform.Field
var1 = 'var1'
#Field String var2 = 'var2'
def var3 = 'var3'
void printVars() {
println var1
println var2
println var3 // This won't work, because not in script scope.
}
def i_am_not_global = 100 // This will not be accessible inside the function
i_am_global = 200 // this is global and will be even available inside the
def func()
{
log.info "My value is 200. Here you see " + i_am_global
i_am_global = 400
//log.info "if you uncomment me you will get error. Since i_am_not_global cant be printed here " + i_am_not_global
}
def func2()
{
log.info "My value was changed inside func to 400 . Here it is = " + i_am_global
}
func()
func2()
here i_am_global variable is a global variable used by func and then again available to func2
if you declare variable with def it will be local, if you don't use def its global
class Globals {
static String ouch = "I'm global.."
}
println Globals.ouch
Like all OO languages, Groovy has no concept of "global" by itself (unlike, say, BASIC, Python or Perl).
If you have several methods that need to share the same variable, use a field:
class Foo {
def a;
def foo() {
a = 1;
}
def bar() {
print a;
}
}
Just declare the variable at class or script scope, then access it from inside your methods or closures. Without an example, it's hard to be more specific for your particular problem though.
However, global variables are generally considered bad form.
Why not return the variable from one function, then pass it into the next?
I think you are talking about class level variables.
As mentioned above using global variable/class level variables are not a good practice.
If you really want to use it. and if you are sure that there will not be impact...
Declare any variable out side the method. at the class level with out the variable type
eg:
{
method()
{
a=10
print(a)
}
// def a or int a wont work
a=0
}
def sum = 0
// This method stores a value in a global variable.
def add =
{
input1 , input2 ->
sum = input1 + input2;
}
// This method uses stored value.
def multiplySum =
{
input1 ->
return sum*input1;
}
add(1,2);
multiplySum(10);
Could not figure out what you want, but you need something like this ? :
​def a = { b -> b = 1 }
​bValue = a()
println b // prints 1
Now bValue contains the value of b which is a variable in the closure a. Now you can do anything with bValue Let me know if i have misunderstood your question

Resources