GroovyShell одна скомпилированная строка, вызывающая другую
Если я запускаю GroovyScript, как это:
def gs=new GroovyShell()
gs.setVariable('square',{x->x*x})
gs.evaluate("print square(10)")
Работает просто отлично. Проблема в том, что я хочу, чтобы функция "Квадрат" также была скомпилирована. Я пробовал это:
def gs=new GroovyShell()
gs.setVariable('square',gs.parse("{x->x*x}"))
gs.evaluate("print square(10)")
но это не работает, я уверен, что это потому, что объект "Script", возвращаемый gs.parse, не действует как замыкание - но я не хочу менять синтаксис второй строки - если Я сделал, было бы много решений...
Есть идеи?
РЕДАКТИРОВАТЬ: После написания этого я понял, что можно было бы просто объединить две строки и проанализировать их один раз, поэтому каждый раз, когда я хотел запустить скрипт, который использует функцию square(), мне нужно было бы добавить текст "def square" (x){x*x)\n"к сценарию...
Я могу сделать это, но это немного странно, поэтому я все еще открыт для других ответов.
1 ответ
Очень близко!
Вам нужно использовать evaluate
вместо разбора, чтобы получить Closure обратно из GroovyShell для передачи в качестве переменной square
:
def gs=new GroovyShell()
gs.setVariable( 'square', gs.evaluate( '{ x -> x * x }' ) )
gs.evaluate( 'print square(10)' )
Нашел это круто и увлекся... Вы можете иметь замыкания в зависимости друг от друга, например, так:
def varMap = [
square: '{ x -> x * x }',
pyth: '{ x, y -> Math.sqrt( square( x ) + square( y ) ) }'
]
// Create a map of name->Closure set each into the shell
// in turn, so later Closures can depend on earlier ones in
// the list
varMap = new GroovyShell().with { shell ->
varMap.collectEntries { name, func ->
// Get the closure
def fn = shell.evaluate( func )
// Set it into this current shell
shell.setVariable( name, fn )
// And return the Entry name->Closure
[ (name): fn ]
}
}
// Ok, this is what we want to run
def command = 'println pyth( 3, 4 )'
new GroovyShell().with { shell ->
// Set all the vars up
varMap.each { name, fn ->
shell.setVariable( name, fn )
}
// Then run the command
shell.evaluate( command )
}