haj has asked for the wisdom of the Perl Monks concerning the following question:
I guess we have all been there: You make an "obviously trivial" change ... and the code fails to behave. This is a stripped down version of the "good" code:
use 5.030; use warnings; my @subrefs = (); for my $i (1..3) { push @subrefs, sub { print $i; }; } for (@subrefs) { $_->(); }
This prints 123, as I would expect.
The "trivial" change:
use 5.030; use warnings; my @subrefs = (); my $i = 0; for (1..3) { $i++; push @subrefs, sub { print $i; }; } for (@subrefs) { $_->(); }
This prints 333. WTF?
It seems the anonymous subroutine is not built with the value of $i, but with a reference to $i. I would not have expected this. Is this a bug, a quirk, or something which can be found documented somewhere?
Edited to add:
I wrote that bad code BC (Before Coffee), remembering that I had done something very similar before. I have now dug that up:
use 5.030; use warnings; my @subrefs; my $i = 0; for (1..3) { push @subrefs, sub { print ++$i }; } for (@subrefs) { $_->(); }
This prints 123. The difference is that the increment is done when the subroutine is called, not when the subs are declared and pushed to the array. In BC state I failed to see that difference.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Closures and scope of lexicals
by ysth (Canon) on Oct 30, 2024 at 18:46 UTC | |
by haj (Vicar) on Oct 30, 2024 at 20:54 UTC | |
by jdporter (Paladin) on Oct 31, 2024 at 13:03 UTC | |
by LanX (Saint) on Oct 31, 2024 at 03:00 UTC | |
Re: Closures and scope of lexicals
by hippo (Archbishop) on Oct 30, 2024 at 18:12 UTC | |
Re: Closures and scope of lexicals
by LanX (Saint) on Oct 30, 2024 at 18:14 UTC | |
Re: Closures and scope of lexicals
by ikegami (Patriarch) on Oct 31, 2024 at 10:13 UTC | |
by haj (Vicar) on Oct 31, 2024 at 15:32 UTC | |
by LanX (Saint) on Oct 31, 2024 at 14:07 UTC | |
by ikegami (Patriarch) on Oct 31, 2024 at 14:25 UTC | |
by LanX (Saint) on Oct 31, 2024 at 14:31 UTC | |
by ikegami (Patriarch) on Oct 31, 2024 at 14:35 UTC | |
| |
by ikegami (Patriarch) on Oct 31, 2024 at 14:38 UTC |