closures = []
vals = ('a'..'z').to_a
until vals.empty?
val = vals.shift()
closures << lambda { puts val }
end
closures.each { |l| l.call() }
ビットは驚くべきことであるすべての呼び出しルビーラムダキャプチャ:奇妙な効果と回避策
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() }
このプリント「」に「Z」のために、このRubyコードを印刷「Z」、それは次のようになりますよう期待される。
ので、私はここを参照すると、彼らの創造
の瞬間にそれらのパラメータを取得するRubyのラムダでは、特定の不正行為である、誰もがRubyの仕様を引用して、この効果を説明していただけますか? (私のRubyは2.2.5p319/Cygwinです)
これはRubyのバグトラッカーのバグとして報告されるべきですか?
これは予期された動作ですか?
、または既にRubyのいくつかのバージョンで修正されていますか?あなたの回答を事前に
おかげ
UPDATE。 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;
JavaScriptで同じ理由で同じことが起こります。これは 'val'が評価されるときの問題です。試してみましょう 'v = 6; f = - > {puts v}; f.call; v = 11; f.call'を表示します。 –
'val'は参照ですが、closuresはそのスコープを覚えていますが、そのスナップショットは作成しません。 Perlでメモリが賢明であるというのは悪い考えです – Tiago
: 'use strict; 警告を使用します。 my @vals = 'a' .. 'z'; my @subs =(); while(@vals){ my $ val = shift @vals; push @subs、sub {print "$ val \ n"; }; } @subsの$ _->(); ' 'a'から 'z'が期待通りに印刷されます
これはどのように説明できますか? –