我是Ruby的新手,一些关闭逻辑让我很困惑.考虑以下代码:
array = []
for i in (1..5)
array << lambda {i}
end
array.map{|f| f.call} # => [5, 5, 5, 5, 5]
Run Code Online (Sandbox Code Playgroud)
这对我来说很有意义,因为我被绑定在循环之外,因此每次循环都会捕获相同的变量.我也觉得使用每个块可以解决这个问题:
array = []
(1..5).each{|i| array << lambda {i}}
array.map{|f| f.call} # => [1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)
...因为我现在每次都被单独宣布.但现在我迷路了:为什么我不能通过引入一个中间变量来修复它?
array = []
for i in 1..5
j = i
array << lambda {j}
end
array.map{|f| f.call} # => [5, 5, 5, 5, 5]
Run Code Online (Sandbox Code Playgroud)
因为j每次循环都是新的,我认为每次传递都会捕获一个不同的变量.例如,这绝对是C#的工作原理,以及我认为 - Lisp的行为与let有关.但在Ruby中并没有那么多.真的发生了什么?
编辑:查看答案中的评论; 问题似乎是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
Run Code Online (Sandbox Code Playgroud)
好的,这太荒谬了.每当我尝试回答有关for循环如何在Ruby中工作的问题时,我就错了.
这样做的原因当然是我不在forRuby中使用循环,其他人也不使用循环,所以对我来说真的没关系:-)
无论如何,为了一劳永逸地解决这个问题,我直接找到了最终资源,即2009年12月1日的IPA Ruby语言规范草案(注定要成为ISO Ruby语言规范):
§11.4.1.2.3
for表达式句法
- for-expression → for for-variable in 表达式 do子句 end
- for-variable → 左侧 | 多左手侧
在表达上的表达不应是跳的表达.
语义
甲用于表达如下评价:
- 评估表达式.让我们
O因此而产生的价值.让
E是初级方法调用形式的基本表达式 [无线-终止这里] .each do | 块正规参数列表 | 块体 end,其中所述的值基本表达式是O,则块正规参数列表是为变量,所述块体是所述化合物语句的的do-子句.评估
E,但跳过§11.2.2的步骤c.所述的值对于表达是所得到的调用的值.
好吧,基本上这意味着
for for_variable in expression
do_clause
end
Run Code Online (Sandbox Code Playgroud)
被翻译成
O = expression
O.each do |for_variable|
do_clause
end
Run Code Online (Sandbox Code Playgroud)
或者,在您的情况下:
for i in 1..5
puts j if i > 1 #undefined local variable or method `j' (NameError)
j = i
end
Run Code Online (Sandbox Code Playgroud)
被翻译成
(1..5).each do |i|
puts j if i > 1 #no excpetion here, works just fine ??!!??
j = i
end
Run Code Online (Sandbox Code Playgroud)
啊哈!但我们忘记了什么!这是一个不祥的"跳过§11.2.2的步骤c".事情!那么,它说什么呢?
- 将一组空的局部变量绑定推送到⟦local-variable-bindings⟧.
注意步骤b
- 将执行上下文设置为
Eb.
是不是跳过.
因此,据我所知,for循环获得自己的执行上下文,它以当前执行上下文的副本开头,但它没有获得自己的一组局部变量绑定.IOW:它获得自己的动态执行上下文,但不是它自己的词法范围.
我必须承认,我仍然不确定我是否完全理解它,但它没有比这更精确.
| 归档时间: |
|
| 查看次数: |
748 次 |
| 最近记录: |