y = lambda { z }
z = 9
y.call
=> NameError: undefined local variable or method `z' for main:Object
y = lambda { z }
y.call
=> 9
我认为有一个块的想法推迟了块内部代码的执行。你能解释一下吗?
答案 0 :(得分:2)
在第一行中,当创建块时,根本就没有z
可以被捕获"在街区之前。当您第二次写y = lambda { z }
时,会有z
。
该块采用周围变量的一种快照。在这种情况下,第一次没有名为z
的变量。
答案 1 :(得分:2)
当你定义一个lambda时,它会得到一个闭包,它包含对定义时范围中所有变量的引用。 lambda总是可以访问它已“关闭”的每个变量的当前值,但是新定义的变量不会追溯地添加到闭包中。所以当你这样做时:
x = 5
y = lambda { x + z }
z = 7
lambda y
可以访问x
的值,但不能访问z
,因为在定义lambda时只存在x
。但如果你这样做:
x = 5
z = 0
y = lambda { x + z }
z = 7
y.call
# => 12
然后一切都会好的。
答案 2 :(得分:2)
lambda
创建所谓的lexical closure,这意味着它捕获对封闭环境的引用,并且可以在创建闭包时使用范围内的变量。
y = lambda { z } # Woops! There's no variable named `z`!
如果在创建闭包后创建名为z
的变量,则无关紧要;关闭的想法是它在特定时刻捕获环境。
理论上,您可能希望在创建lambda时出现错误,因为可以对其进行分析并确定将取消引用尚未定义的变量。但是,Ruby不会那样工作;只有在评估代码时才会出现尝试访问未定义变量的错误。
当您创建第二个闭包时,几行后, 会捕获z
存在的环境:
y = lambda { z } # This closure is broken and can't be fixed
z = 9
y = lambda { z } # This is a new closure, and `z` is accessible within it
我认为有一个块的想法推迟了块内部代码的执行。
排序,但它与简单地复制和粘贴lambda中的代码并在调用它时进行评估不同。 eval
字符串会这样做:
y = "z"
z = 9
eval(y)
# => 9
同样,闭包的想法是它捕获代码和环境。
答案 3 :(得分:1)
undefined local variable or method 'z' for main:Object
在未创建局部变量时出现。仅由assignment
操作创建的局部变量。
您的第一个y = lambda { z }
无法绑定z
,因为此z
定义后定义了lambda
。
以下作品:
y = lambda { z }
y.call
=> 9
在第二个lambda定义之前定义z = 9
。