有两段代码
a = 1 l = -> { puts a } l.call
l = -> { puts b } b = 1 l.call
其中第一段代码正常,而第二段代码会抛异常,因为声明 l 的时候上下文并没有 a。
原理应该类似 eval 不能在上下文中声明一个局部变量,l 运行时的上下文是声明时的上下文,不随外部上下文改变而改变,那有没有办法让第二段代码运行起来呢
ruby 中估计没有能让第二种代码运行的办法,有这种办法俺也不用。
在 python 和 js 中,第二种代码是能正常运行。然而这种特性,估计也只有面试能用到...
这种不知道是否能满足楼主需求
l = -> (ctx) { eval('puts b', ctx) } b = 1 l.call(binding)
这个是因为 lambda 在创建的时候已经编译好了,用 RubyVM::InstructionSequence.disasm 可以看 lambda 编译后的字节码,会发现如果当时有变量字节码是读取 local,否则是调用方法。所以不是作用域的问题,在其他脚本语言里也没有。
这个问题无法避免,可以使用实例变量等等来绕过。
感谢提示,换个思路,把局部变量换成方法,问题解决了。
l = -> { puts c } define_method(:c) { 3 } l.call
ps: 通过实例变量可以绕过这个我知道,但是写起来就不太雅观~