- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
closures = []
vals = ('a'..'z').to_a
until vals.empty?
val = vals.shift()
closures << lambda { puts val }
end
closures.each { |l| l.call() }
这段 Ruby 代码会为每次调用打印“z”,这有点令人惊讶
def closure(val)
lambda {puts val}
end
closures = []
vals = ('a'..'z').to_a
until vals.empty?
val = vals.shift()
closures << closure(val)
end
closures.each { |l| l.call() }
这会按预期打印“a”到“z”。
所以我在这里看到的是 Ruby lambda 在创建参数时捕获参数的某些不当行为
任何人都可以通过引用 Ruby 规范来解释这种效果吗? (我的 Ruby 是 2.2.5p319/Cygwin)
这应该作为 Ruby 错误跟踪器中的错误报告吗?
或者这是预期的行为?
或者它已经在某些更高版本的 Ruby 中得到修复?
提前感谢您的回复
更新。这是移植到 Perl 的相同代码。令人惊讶的是,它按预期工作:
use strict;
use warnings;
my @vals = 'a'..'z';
my @subs = ();
while (@vals) {
my $val = shift @vals;
push @subs, sub { print "$val\n"; };
}
$_->() for @subs;
最佳答案
在 Ruby 中,变量是通过引用而不是值来捕获的(在 Python、JavaScript 和许多其他语言中也是如此)。此外, val
的范围是函数范围,而不是循环内部的范围,因此您不会在循环的每次迭代中都获得新变量 val
-- 是同一个变量 val
;您只是在每次迭代中为其分配另一个值。
在循环的每次迭代中,都会创建一个引用变量 val
的闭包——完全相同的变量 val
。因此,当稍后对闭包求值时,它们都读取相同的值——此时(单个)变量 val
的值。
当你将它传递给一个方法并在方法内部创建闭包时,它是不同的,因为闭包捕获的变量是方法体中的 val
closure
,范围限于该方法。每次调用方法closure
,都会得到一个新的变量val
,其值为传入的值,此后永远不会改变(closure中没有任何内容)
分配给它)。所以后面这个值被闭包读取的时候,仍然是创建闭包时传递给调用closure
的值。
关于 ruby lambda 捕获 : a weird effect and workaround,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39882131/
我是一名优秀的程序员,十分优秀!