【发布时间】:2010-05-14 02:16:25
【问题描述】:
我对 Ruby 有点陌生,一些闭包逻辑让我感到困惑。考虑这段代码:
array = []
for i in (1..5)
array << lambda {i}
end
array.map{|f| f.call} # => [5, 5, 5, 5, 5]
这对我来说很有意义,因为 i 被绑定在循环之外,因此每次循环都会捕获相同的变量。对我来说,使用 each 块可以解决这个问题也很有意义:
array = []
(1..5).each{|i| array << lambda {i}}
array.map{|f| f.call} # => [1, 2, 3, 4, 5]
...因为 i 现在每次都被单独声明。但是现在我迷路了:为什么我不能通过引入一个中间变量来修复它?
array = []
for i in 1..5
j = i
array << lambda {j}
end
array.map{|f| f.call} # => [5, 5, 5, 5, 5]
因为 j 每次循环都是新的,所以我认为每次循环都会捕获不同的变量。例如,这绝对是 C# 的工作方式,以及——我认为——Lisp 是如何使用 let 的。但在 Ruby 中没有那么多。到底发生了什么?
编辑:请参阅答案中的 cmets;问题似乎是 j 仍在循环之外的范围内。循环中的作用域如何真正起作用?
编辑:我想我还是不明白; if 循环不创建新的范围,为什么这样:
for i in 1..5
puts j if i > 1 #undefined local variable or method `j' for main:Object (NameError)
j = i
end
【问题讨论】:
-
与
puts j,j 尚未分配给任何东西。局部变量需要先分配才能使用它们(它们不会自动激活。)只是 for 循环没有在其中创建新的范围,所以 j 永远不会在它的末尾超出范围。跨度>