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 )
}
Другие вопросы по тегам