Нужна помощь по синтаксису Groovy для создания замыкания из строки

Я пытаюсь создать замыкание из строки. Код внутри замыкания ссылается на функцию build () DSL. Ошибки, которые я получаю, подразумевают, что Groovy пытается выполнить закрытие вместо того, чтобы просто объявить его. Каков правильный синтаксис для этого? Вот некоторые из конструкций, которые я уже пробовал.

sh = new GroovyShell() 
cl = sh.evaluate( '{ build("my job") }' } 
=> Ambiguous expression could be either a parameterless closure expression or an isolated open code block;

sh = new GroovyShell() 
cl = sh.evaluate( 'L: { build("my job") }' } 
=> No signature of method: Script1.build() is applicable ...

cl = Eval.me( 'L: { build("my job") }' } 
=> No signature of method: Script1.build() is applicable ...

cl = Eval.me( 'L: { com.flow.FlowDelegate.build("my job") }' } 
=> No such property: com for class: Script1

Пример, которому я пытаюсь следовать, взят из: Загрузить код закрытия из строки в Groovy


person ScaryGhast    schedule 23.06.2013    source источник


Ответы (4)


А как насчет возврата закрытия из скрипта?

Eval.me("return { build('my job') } ")

Что вы собираетесь использовать L:? Возвращаете карту? В таком случае можно использовать квадратные скобки:

groovy:000> a = Eval.me("[L: { build('test for') }]")
===> {L=Script1$_run_closure1@958d49}
groovy:000> a.L
===> Script1$_run_closure1@958d49
person Will    schedule 23.06.2013
comment
Я думаю, что L: добавлен в соответствии с предложением консоли Groovy. Неоднозначное выражение может быть либо выражением закрытия без параметров, либо изолированным блоком открытого кода, решение: добавить явный список параметров закрытия, например {it - ›...}, или принудительно обработать его как открытый блок, присвоив ему метку, например Л: {...} - person Alexander Suraphel; 11.02.2014

Рассмотрим пример ниже. Ключ в том, чтобы явно указать замыкание без параметров.

def build = { def jobName ->
    println "executing ${jobName}"
}

// we initialize the shell to complete the example
def sh = new GroovyShell()
sh.setVariable("build", build)

// note "->" to specify the closure
def cl = sh.evaluate(' { -> build("my job") }')

println cl.class
cl.call()
person Michael Easter    schedule 24.06.2013

Помимо ответа Майкла Истера, вы также можете передать привязку скрипта к GroovyShell.

def build = { ->
  "BUILD $it"
}

def shell = new GroovyShell( this.binding )
def c = shell.evaluate( "{ -> build( 'tim_yates' ) }" )

c()
person tim_yates    schedule 23.06.2013
comment
Является ли Groovy Shell безопасным для потоков? Могу ли я создать только один и повторно использовать его в Grails? - person raffian; 28.05.2014

Если вы оцениваете String из сценария конфигурации DSL, вам не нужно создавать объект GroovyShell.

Ваш сценарий будет запущен как подкласс Script, который предоставляет удобный метод для оценки строки с текущей привязкой.

public Object evaluate(String expression)
            throws CompilationFailedException

A helper method to allow the dynamic evaluation of groovy expressions using this scripts binding as the variable scope

В этом случае вам просто нужно позвонить evaluate('{ -> build("my job") }').

person Jan Gassen    schedule 31.08.2015