提问人:stdout 提问时间:10/16/2018 更新时间:10/17/2018 访问量:831
在 groovy 中查找闭包的自由变量列表/映射
Finding list/map of free variable(s) of a closure in groovy
问:
这是我简单时髦的脚本;
def fourtify(String str) {
def clsr = {
str*4
}
return clsr
}
def c = fourtify("aa")
println("binding variables: ${c.getBinding().getVariables()}")
...
我在这里要做的就是能够使用闭包实例访问自由变量“”,以更好地理解闭包在幕后的工作方式。也许就像 Python 的方法一样。str
locals()
有没有办法做到这一点?
答:
您定义的闭包不会在 object 中存储任何内容 - 它只是返回作为变量传递的 String,重复 4 次。binding
str
此对象存储定义的所有变量,但未指定其类型或使用关键字。它是通过Groovy元编程功能(以及更具体的方法)完成的。因此,当您定义一个变量时,例如:binding
def
getProperty
setProperty
s
def clsr = {
s = str*4
return s
}
然后,此闭包将创建一个绑定,其中包含从表达式中计算的键和值。此绑定对象只不过是通过 和 方法访问的映射。因此,当 Groovy 执行时,它会调用,因为没有定义变量/属性。如果我们做一个稍微简单的改变,比如:s
str * 4
getProperty
setProperty
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]
希望对你有所帮助。
评论
在您的示例中是方法/函数的参数str
fortify
但是,也许以下示例会让您更好地理解 Closure:
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]
Python 的函数更好地匹配 groovy.lang.Script.getBinding()locals()
下面是一个带有脚本的简单示例:
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"
评论
delegate
delegate.metaClass.properties.collect{it.name}
delegate.getClass().getDeclaredFields()
str
评论