[groovy-user] Overriding script variables

1,240 views
Skip to first unread message

Paolo Di Tommaso

unread,
Jun 4, 2012, 6:20:04 PM6/4/12
to us...@groovy.codehaus.org
Dear all, 

Is there a way to override the value of of a script defined variable? 

Take in consideration the following Groovy script: 

def y = "world!"
println "$x $y"


Now, I will execute it using the following fragment: 


def gcl = new GroovyClassLoader()
Script script = gcl.parseClass(new File("./script.groovy")).newInstance()
script.setProperty("x", "Hola")
script.setProperty("y", "mundo!")
script.run()


Since, I'm setting the "x" and "y" value with the method setProperty, I was expecting the get the following string as result: 

"Hola mundo!"

Instead the setProperty does nothing for the attribute "y" since it is already defined in the script, and the script returns  

"Hola world!"


Is there a way to override a variable value defined by a script, the "y" variable in this trivial example  ?? 


Thank you all. 

Paolo

Wujek Srujek

unread,
Jun 5, 2012, 1:56:05 AM6/5/12
to us...@groovy.codehaus.org
You are setting script variables, but the y one is a local variable, which yo can't override. Try declaring it without 'def', which should make it a binding variable, i.e., overridable by setProperty.

wujek

Paolo Di Tommaso

unread,
Jun 5, 2012, 2:38:25 AM6/5/12
to us...@groovy.codehaus.org
Hi,

I've figure out that, but this still does not solve the problem because I'm unable to override the binding variable using the setProperty method. 

My use case is the following: 

I have a groovy script where some binding variables are defined. The assignation is meant to provide the default values if no binding values are provided for them. For example:

For example: 

x = "Hello" 
y = "word!" 
print "$x $y"

When the script is evaluated I would have the ability to override some or all of them. 

For example:

script.setProperty("x", "Hola")
script.setProperty("y", "mundo!")

But the binding values specified by the setProperty are lost, because the assignation in the script override them.

So I get the string "Hello world!" in case. Instead I would like to control the result using the values specified by the setProperty method. 


Is there a way to do that?! 

Thanks,
Paolo

Wujek Srujek

unread,
Jun 5, 2012, 3:11:52 AM6/5/12
to us...@groovy.codehaus.org
I think by the time you call the print function, the x and y are re-set in the script itself - it can't work the way you want it to. How about sth like this:

//x = 'Hola'
//y = 'Mundo'

def setDefsIfNeeded(Map defs) {
  defs.each { key, value ->
      if (!binding.variables.containsKey(key)) {
          binding[key] = value
      }
  }
}

setDefsIfNeeded x: 'Hello', y: 'World'

println "$x, $y!"

This will print out 'Hello, World!' as the binding is clean. Now, uncomment the first lines to simulate the binding being pre-set before calling the script, and you will see 'Hola, Mundo!'.

I agree it is not beautiful, but I don't know any other way of doing that. You could name the method better, or even hide the I don't know the full context. You can also do this:

//x = 'Hola'
//y = 'Mundo'

setDefs = { Map defs ->
  defs.each { key, value ->
      if (!binding.variables.containsKey(key)) {
          binding[key] = value
      }
  }
}

setDefs x: 'Hello', y: 'World'

println "$x, $y!"


and actually set the setDefs closure to the binding, so that it is not defined in each script.

These are just some of my ideas, maybe others will be able to come up with sth better.


Wujek

Wujek Srujek

unread,
Jun 5, 2012, 3:16:00 AM6/5/12
to us...@groovy.codehaus.org
You could also define your custom binding, that doesn't set variables when they are set already. In that case, doing in your script:

x = 'Hello'

would have no effect if the (custom) binding already had a mapping for 'x'. This would of course prevent you from resetting any binding variables, which might be unacceptable, but also a very good thing. All depends on the full context.

Continuing with the setDefs closure, you could define your custom Script subclass that defines such a method, in which case you don't have to set it to the binding any more.

wujek

Paolo Di Tommaso

unread,
Jun 5, 2012, 5:10:09 AM6/5/12
to us...@groovy.codehaus.org
Hi Wujek, 

The custom binding it's a good idea, and I think it's the best solution for my use case!

Thanks for your tips.

Best, 
Paolo
Reply all
Reply to author
Forward
0 new messages