* Mark-Jason Dominus <perlbug-followup@perl.org> [2016-09-29 03:00]: > The following program: > > my $i; > sub announce { printf "Count %d\n", $i } > > for $i (1..3) { > announce(); > } > > It emits > > Count 0 > Count 0 > Count 0 > > But it should be > > Count 1 > Count 2 > Count 3 Maybe. But that might affect this: $ perl -E 'my @i; for my $i (5..8) { push @i, sub { say $i } }; $_->() for @i' 5 6 7 8 That behaviour must not break under any circumstances. To make that work, in each iteration, foreach rebinds the name $i to the scalar for that iteration: perl -E 'my @i = (5..8); for my $i (@i) { say \$i eq \$i[$a++] }' 1 1 1 1 It seems to me that this binding is necessarily lexical to the loop block scope. Meanwhile the `announce` sub has already closed over $i at compile time. I don’t know that it’s possible to change either of these facts. Not to mention doing it in such a way that closing over the loop variable at runtime would remain unaffected. The straightforward way to get your “correct” output would be to change foreach to do local()-style value shadowing with the same scalar. Which would break a huge amount of code, and I think it would generally be a worse default, even though one consequence of the current behaviour is the case you ran into here. You can always use while() when you need it. > Also, when correcting that bug, please make sure this is also corrected: > > for my $i (1..3) { > sub announce { printf "Count %d\n", $i } > announce(); > } > > It shows the same wrong behavior. That sub is compiled just once despite its placement inside the loop and it binds $i at compile time. Arguably perl ought to warn about this, the same way that it warns when you make the same mistake but you write it this way: sub do_announce { my $i = shift; sub announce { printf "Count %d\n", $i } announce(); } That throws the infamous “will not stay shared” warning. But you would not want this to start warning: { my $count = 0; sub announce { printf "Count %d\n", $count } } I don’t know how hard it would be to distinguish sure-fire warn-worthy situations from benign ones here. Regards, -- Aristotle Pagaltzis // <http://plasmasturm.org/>Thread Previous | Thread Next