在groovy中查找闭包的自由变量列表/映射
这是我的简单groovy脚本在groovy中查找闭包的自由变量列表/映射,groovy,properties,closures,free-variable,Groovy,Properties,Closures,Free Variable,这是我的简单groovy脚本 def fourtify(String str) { def clsr = { str*4 } return clsr } def c = fourtify("aa") println("binding variables: ${c.getBinding().getVariables()}") ... 我在这里要做的就是能够使用closure实例访问自由变量“str”,从而更好地理解closure在幕后的工作方式。比
def fourtify(String str) {
def clsr = {
str*4
}
return clsr
}
def c = fourtify("aa")
println("binding variables: ${c.getBinding().getVariables()}")
...
我在这里要做的就是能够使用closure实例访问自由变量“str
”,从而更好地理解closure在幕后的工作方式。比如Python的locals()
方法
有办法做到这一点吗?您定义的闭包不在
绑定
对象中存储任何内容-它只返回作为str
变量传递的字符串,重复4次
此binding
对象存储所有定义的变量,而不指定其类型或使用def
关键字。它是通过Groovy元编程特性完成的(getProperty
和setProperty
方法更具体)。因此,当您定义变量s
时,如下所示:
def clsr={
s=str*4
返回s
}
然后,这个闭包将创建一个带有键s
和从表达式str*4
计算的值的绑定。这个绑定对象只是一个通过getProperty
和setProperty
方法访问的映射。因此,当Groovy执行s=str*4
时,它调用setProperty('s',str*4)
,因为变量/propertys
没有定义。如果我们做一个稍微简单的改变,比如:
def clsr={
def s=str*4//或字符串s=str*4
返回s
}
然后将不会创建绑定s
,因为setProperty
方法不会执行
对你的例子的另一个评论。若您想在binding对象中看到任何内容,则需要调用返回的闭包。在上面显示的示例中,将返回闭包,但从未调用它。如果您这样做:
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
但是,以下示例可能会让您更好地理解:
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()
下面是一个简单的脚本示例:
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"
这就是我在开始时所想的,所以我尝试在闭包实例上使用getBinding()方法获取变量(包括“自由”变量)。此外,我更感兴趣的是在编译脚本后获取闭包关闭的“自由”变量,而不是检索有关参数的信息。@zgulser,闭包没有“自由”变量。使用delegate
可以访问声明此闭包的对象,并使用groovy元类请求声明的类字段:delegate.metaclass.properties.collect{it.name}
或使用java nativedelegate.getClass().getDeclaredFields()
。但是,您不能访问在方法/函数中声明的局部变量。我不认为这是完全正确的-。我知道Groovy中的委托概念,但在我的情况下,我认为“str”不能是任何委托的一部分,因为它是函数的局部变量。在您的示例中,无法获取str
it。除非你想用AstBuilder来分析代码……我明白你的意思,但我还是不明白为什么我在任何地方都看不到“free”变量“str”——即使在我删除了类型字符串之后?我的观点是,在编译脚本时,变量“str”应该存储在某个地方,因此当我调用闭包时,它可以通过查看所有者或委托或其他对象来解析“str”名称。希望它更有意义。