En este ejemplo, el script Script2.groovy
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ cat -n Script2.groovy 1 println "In Script2" 2 shell = new GroovyShell() 3 shell.evaluate(new File('Script1.groovy'))llama al script
Script1.groovy
:
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ cat -n Script1.groovy 1 println "Hello from Script1"Para ello primero se crea un objeto GroovyShell y después se llama al método
evaluate
:
En el ejemplo evaluate
recibe una cadena conteniendo el nombre de fichero,
pero es posible obtener el script de diversas formas:
Object evaluate(File file)
Evaluates some script against the current Binding and returns the result
Object evaluate(GroovyCodeSource codeSource)
Evaluates some script against the current Binding and returns the result
Object evaluate(Reader in)
Evaluates some script against the current Binding and returns the result
Object evaluate(Reader in, String fileName)
Evaluates some script against the current Binding and returns the result
Object evaluate(String scriptText)
Evaluates some script against the current Binding and returns the result
Object evaluate(String scriptText, String fileName)
Evaluates some script against the current Binding and returns the result
Object evaluate(String scriptText, String fileName, String codeBase)
Evaluates some script against the current Binding and returns the result.
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ groovy Script2.groovy In Script2 Hello from Script1También es posible llamar simplemente a
evaluate
:
$ cat -n Script3.groovy 1 println "In Script3" 2 evaluate(new File('Script1.groovy')) $ groovy Script3.groovy In Script3 Hello from Script1
Este script hace uso de una variable $name
que definiremos en otro script:
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ cat -n Script1a.groovy 1 println "Hello $name" 2 name = "Dan"
Aunque los atributos y variables locales deben ser declarados antes de su uso dentro de una clase, en los scripts es posible usar variables no declaradas. En ese caso se asume que las variables vienen del binding del script y que serán añadidas a este si aún no están allí.
In computer science, binding is the creation of a simple reference to something that is larger and more complicated and used frequently. The simple reference can be used instead of having to repeat the larger thing. A binding is such a reference
The terms language binding and name binding refer to both the linking of libraries to application programs, and to the way symbols (variable names) are handled by compilers.
In programming languages, these terms mean the references of an identifier to a value. In this context, binding is the act of associating a name or symbol with a machine address, and this association may occur either at compile time, in which case it is called 'static linking', or it may occur dynamically at runtime, which is called 'dynamic linking'. The terms binding and linking are used interchangeably in some contexts.
Static binding has an additional characteristic: it prevents libraries from being updated (recompiled) independently of applications.
El siguiente script crea un objeto GroovyShell
pasándole como argumento el objeto
Binding
del script actual.
Este objeto representa los binding (el mapa) de las variables en el script.
Al pasarlo como argumento conseguimos que las variables pueden ser alteradas desde fuera del script
y creadas fuera y pasadas al mismo. Citando la documentación:
The public class Binding represents the variable bindings of a script which can be altered from outside the script object or created outside of a script and passed into it.
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ cat -n Script2a.groovy 1 println "In Script2a" 2 name = "Juana" 3 4 shell = new GroovyShell(binding) 5 result = shell.evaluate(new File('Script1a.groovy')) 6 7 println "Script1a returned: $result" 8 println "Hello $name"
En efecto:
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ groovy Script2a.groovy In Script2a Hello Juana Script1a returned: Dan Hello Dan
El valor retornado por evaluate
es el valor retornado por el script.
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ cat Script5.groovy Binding binding = new Binding(); binding.setVariable("foo", new Integer(2)); GroovyShell shell = new GroovyShell(binding); Object value = shell.evaluate(new File('Script1b.groovy')) println value println binding.getVariable("x") assert value.equals(new Integer(20)); assert binding.getVariable("x").equals(new Integer(123));
Estos son los contenidos del script Script1b.groovy
:
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ cat Script1b.groovy println 'Hello World!' x = 123 return foo * 10Al ejecutar
Script5.groovy
vemos como la variable foo
está
en el binding de Script1b.groovy
cuando éste se ejecuta:
generaciondecodigos@nereida:~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ groovy Script5.groovy Hello World! 20 123Además
Script5.groovy
obtiene e imprime el valor retornado por Script1b.groovy
y accede a la variable x
del mismo.
Utilizaremos el método run
en vez de evaluate
si se quieren pasar los argumentos usando la línea de comandos:
Object run(File scriptFile, List list)
A helper method which runs the given script file with the given command line arguments
Object run(File scriptFile, String[] args)
Runs the given script file name with the given command line arguments
Object run(Reader in, String fileName, String[] args)
Runs the given script with command line arguments
Object run(String scriptText, String fileName, List list)
A helper method which runs the given cl script with the given command line arguments
Object run(String scriptText, String fileName, String[] args)
Runs the given script text with command line arguments
El siguiente ejemplo ilustra el modo de uso. Código del llamador:
~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ cat -n run.groovy 1 binding = new Binding() 2 binding.setVariable("name", "Juan") 3 4 shell = new GroovyShell(binding) 5 6 value = shell.run(new File('Script1c.groovy'), ['a', 'b']) 7 8 println "Script1c returned ${value}" 9 10 println "z = ${binding.getVariable("z")}"Este es el código del script llamado:
~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ cat -n Script1c.groovy 1 println "Script1c: args received ${args}" 2 println "Script1c: Hello $name" 3 name = "Dan" 4 z = 4 5 8y este el resultado de la ejecución:
~/src/groovy/separatedcomp/groovyscriptsfromgroovy$ groovy run.groovy Script1c: args received [a, b] Script1c: Hello Juan Script1c returned 8 z = 4
El método parse
de los objetos GroovyShell
retorna un objeto de la clase Script.
Estos objetos disponen de un método run
:
$ cat parseandrun.groovy Binding binding = new Binding() binding.setVariable("x", new Integer(2)) def shell = new GroovyShell(binding) def script = shell.parse( ''' x++ println x ''' ) 10.times { script.run() }Cuando se ejecuta el programa anterior produce el siguiente resultado:
$ groovy parseandrun.groovy 3 4 5 6 7 8 9 10 11 12
El siguiente programa pone en práctica lo aprendido para proveer una calculadora.
Las cadenas leídas en stdin
son evaluadas dentro de un script Groovy
y el resltado es mostrado por pantalla:
~/Lgroovy/separatedcomp/groovyscriptsfromgroovy$ cat -n calc.groovy 1 def stdin = new BufferedReader(new InputStreamReader(System.in)) 2 Binding binding = new Binding() 3 def shell = new GroovyShell(binding) 4 5 int c = 1; 6 print "> " 7 stdin.eachLine{ input -> 8 def script = shell.parse(input) 9 def a = script.run() 10 println a 11 print "> " 12 }
sigue un ejemplo de ejecución:
generaciondecodigos@nereida:~/Lgroovy/separatedcomp/groovyscriptsfromgroovy$ groovy calc.groovy > a =2*3 6 > a+2 8 > b = a-3 3 > Math.sqrt(b) 1.7320508075688772 > ^DHemos pulsado la combinación
CTRL-D
para producir la señal de final
de entrada.