Поиск списка / карты свободных переменных в замыкании в Groovy - PullRequest
0 голосов
/ 16 октября 2018

Это мой простой Groovy-скрипт;

def fourtify(String str) {

    def clsr = {
         str*4
    }

    return clsr
}

def c = fourtify("aa")
println("binding variables: ${c.getBinding().getVariables()}")
...

Все, что я пытаюсь сделать, это получить доступ к свободной переменной "str", используя экземпляр closure, чтобы понять, как работает closureсцены немного лучше.Как, например, метод Python locals().

Есть ли способ сделать это?

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

в вашем примере str является параметром метода / функции fortify

однако, возможно, следующий пример даст вам лучшее Закрытие понимание:

def c={ String s,int x-> return s*x }

println( c.getClass().getSuperclass() )     // groovy.lang.Closure
println( c.getMaximumNumberOfParameters() ) // 2
println( c.getParameterTypes() )            // [class java.lang.String, int]

функция locals() Python лучше соответствует groovy.lang.Script.getBinding ()

, и вот простой пример со скриптом:

Script scr = new GroovyShell().parse(''' 
    println this.getBinding().getVariables()  // print "s" and "x"
    z = s*(x+1)                               // declare a new script-level var "z"
    println this.getBinding().getVariables()  // print "s", "x", and "z"
    return s*x 
''')
scr.setBinding( new Binding([
        "s":"ab",
        "x":4
    ]) )
println scr.run() // abababab
println scr.getBinding().getVariables() // print "s", "x", and "z"
0 голосов
/ 16 октября 2018

Определенное вами замыкание ничего не сохраняет в объекте binding - оно просто возвращает строку, переданную как переменную str, повторяется 4 раза.

Этот объект binding хранит все переменные, которые были определеныбез указания их типов или использования ключевого слова def.Это делается с помощью функции метапрограммирования Groovy (точнее, getProperty и setProperty).Поэтому, когда вы определяете переменную s, например:

def clsr = {
     s = str*4
     return s
}

, тогда это закрытие создаст привязку с ключом s и значением, вычисленным из выражения str * 4.Этот объект привязки является ничем иным, как картой, доступ к которой осуществляется с помощью методов getProperty и setProperty.Поэтому, когда Groovy выполняет s = str * 4, он вызывает setProperty('s', str * 4), поскольку переменная / свойство s не определена.Если мы сделаем немного простое изменение, например:

def clsr = {
     def s = str*4 // or String s = str * 4
     return s
}

, то привязка s не будет создана, потому что метод setProperty не выполняется.

Еще один комментарий к вашему примеру,Если вы хотите увидеть что-либо в объекте привязки, вам нужно вызвать возвращаемое закрытие.В приведенном выше примере возвращаемое замыкание возвращается, но оно никогда не вызывается.Если вы сделаете:

def c = fourtify("aa")
c.call()
println("binding variables: ${c.getBinding().getVariables()}")

, тогда будет вызвано ваше замыкание, и объект привязки будет содержать привязки (если они есть).Теперь, если вы измените свой пример на что-то вроде этого:

def fourtify(String str) {

    def clsr = {
        def n = 4 // it does not get stored as binding
        s = str * n
        return s
    }

    return clsr
}

def c = fourtify("aa")
c.call()
println("binding variables: ${c.getBinding().getVariables()}")

, вы увидите следующие выходные данные:

binding variables: [args:[], s:aaaaaaaa]

Надеюсь, это поможет.

...