Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: Strange behavior of iteration while creating Perl/Tk widgets dynamically

by bliako (Monsignor)
on Oct 29, 2021 at 08:50 UTC ( [id://11138182]=note: print w/replies, xml ) Need Help??


in reply to Strange behavior of iteration while creating Perl/Tk widgets dynamically

Your problem can be demonstrated by following simple code:

my @subs; for(my $i=1;$i<=5;$i++){ push @subs, sub { print "i=$i\n"; }; } $subs[3]->();

Inside the sub, $i is evaluated at the time the sub is called in the context/scope of the for-loop which has now terminated, so $i=5+1=6, which is the expected behaviour.

A workaround would be to create a sub via eval which will force it to consider $i's value at the time of the eval. But I am not sure if this is an elegant solution:

my @subs; for(my $i=1;$i<=5;$i++){ push @subs, eval <<EOE; sub { print "i=$i\n"; }; EOE } $subs[3]->();

btw, once you sort this out, you should start using arrays instead of ${"xx$i"}!

Update: another solution would be to introduce another variable local to the loop scope and use that:

my @subs; for(my $i=1;$i<=5;$i++){ my $j = $i; push @subs, sub { print "i=$i, j=$j\n"; }; } $subs[3]->();

Question: what's the difference between $i and $j, don't they both have the same scope?

bw, bliako

Replies are listed 'Best First'.
Re^2: Strange behavior of iteration while creating Perl/Tk widgets dynamically
by BillKSmith (Monsignor) on Oct 29, 2021 at 14:34 UTC
    The perl foreach (or its alias for) loop does not have this problem.
    my @subs; #for(my $i=1;$i<=5;$i++){ for my $i (1..5) { push @subs, sub { print "i=$i\n"; }; } $subs[3]->();

    OUTPUT:

    i=4
    Bill

      And this code confirms your finding:

      my @subs; for(my $i=1;$i<=2;$i++){ print \$i."\n" } print "----\n"; for my $i (1..2) { print \$i."\n" }

      OUTPUT:

      SCALAR(0x55a429b66a28) SCALAR(0x55a429b66a28) ---- SCALAR(0x56399466d4d8) SCALAR(0x5639946924a0)

      Which made me try this:

      my @subs; my $i; for($i=1;$i<=5;$i++){ push @subs, sub { print "i=$i\n"; }; } $i = 100; $subs[3]->();

      It prints i=100

      bw, bliako

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11138182]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2024-04-23 09:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found