Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re: Closure confusion in Tkx (declarations in loops)

by LanX (Saint)
on Jul 13, 2019 at 12:50 UTC ( [id://11102790]=note: print w/replies, xml ) Need Help??


in reply to Closure confusion in Tkx

Hi

I'm not an expert on Tkx, but I think you might get bitten by the way closure variables are "shared".

Please compare

use strict; use warnings; # ---------- for each @list my @each; for my $i ( 1..3 ) { push @each, sub { warn "each: \t$i" }; } $_->() for @each; # ---------- for c-style my @cfor; for ( my $i = 1 ; $i < 4; $i++ ) { push @cfor, sub { warn "cfor: \t$i" }; } $_->() for @cfor; # ---------- generator sub gen { my ($x)=@_; return sub { warn "gen: \t$x" }; } my @gen; for ( my $i = 1 ; $i < 4; $i++ ) { push @gen, gen($i); } $_->() for @gen;

each: 1 at d:/exp/pm_closure.pl line 10. each: 2 at d:/exp/pm_closure.pl line 10. each: 3 at d:/exp/pm_closure.pl line 10. cfor: 4 at d:/exp/pm_closure.pl line 21. cfor: 4 at d:/exp/pm_closure.pl line 21. cfor: 4 at d:/exp/pm_closure.pl line 21. gen: 1 at d:/exp/pm_closure.pl line 31. gen: 2 at d:/exp/pm_closure.pl line 31. gen: 3 at d:/exp/pm_closure.pl line 31.

actually your case with a c-style loop is how it's supposed to be, your my $x has only one instance and only gets a new value with each iteration.²

for (@list)' is special because the loop var is an alias to the list-value. °

To avoid such confusions it's always safe to call a "generator" sub which returns a closure.

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

footnotes

°) the source of the famous "want stay shared" error. (UPDATE or because it's considered an inside declaration ?)

²) a c-style for is semantically just a while-loop with a prior declaration.

updates
expanded example with clearer output and generator case

Replies are listed 'Best First'.
Re^2: Closure confusion in Tkx (declarations in loops - inner vs outer)
by LanX (Saint) on Jul 13, 2019 at 13:53 UTC
    > ²) a c-style for is semantically just a while-loop with a prior declaration.

    to expand further on this, please see perlsyn#For-Loops

    which means

    for (my $i = 1; $i < 10; $i++) { ... }
    is the same as this:

    { my $i = 1; while ($i < 10) { ... } continue { $i++; } }

    now compare the different effects from an inner declaration ($i) and an outer declaration ($x)

    use strict; use warnings; # ---------- for c-style my @cfor; for ( my $x = 1 ; $x < 4; $x++ ) { my $i = $x; push @cfor, sub { warn "cfor: \ti=$i \tx=$x" }; } $_->() for @cfor; # ---------- while my @values = 1..3; my @while; my $x; while ( my $i = shift @values ) { $x = $i; push @while, sub { warn "while: \ti=$i \tx=$x" }; } $_->() for @while;
    cfor: i=1 x=4 at d:/exp/pm_closure2.pl line 11. cfor: i=2 x=4 at d:/exp/pm_closure2.pl line 11. cfor: i=3 x=4 at d:/exp/pm_closure2.pl line 11. while: i=1 x=3 at d:/exp/pm_closure2.pl line 25. while: i=2 x=3 at d:/exp/pm_closure2.pl line 25. while: i=3 x=3 at d:/exp/pm_closure2.pl line 25.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Thanks Rolf!

      The code works now but I'm still kinda puzzled as to why the c-style for fails in this case. Is this not a bug in perl?

      Regards,

      Lars

        I agree with LanX's explanation here, but here's something I put together that may provide a different viewpoint.

        In the C-style for-loop and in its while-loop equivalent in LanX's examples here, a closure is formed (if that's the correct term) over two variables, $i and $x. The $i variable is created anew in each iteration through each loop (there's a  my $i = ...; within the scope of the loop), but the $x variable is created only once (in each example). Therefore, the closures are over three different versions of a variable named $i, each of which can have a different value, but only over a single version of a variable named $x, which has the value it ends up with at the end of each of the loops.

        In the Perl-style loop example here, the for-loop iterator variable $i is successively aliased to three individual values, each of which individually has a closure formed over it and so can reflect those three values independently; you're seeing the alias of $i in each case and not the value of $i.

        Or so I think...

        Update: And no, the way the C-style for-loop works in Perl is not a bug; it's the way closures work.


        Give a man a fish:  <%-{-{-{-<

        > as to why the c-style for fails in this case.

        Think of lexicals in a scope like having a different references each time the scope is passed at runtime.

        But - like already demonstrated - the first part of the c-style for is outside the block to be implemented as a while.

        More gory details?

        A lexical declaration in a scope reserves - at run time - a storage place in memory which is released at the end of scope.

        No release happens if the ref counter isn't 0, like when the lexical is used in a closure.

        So if the last lexical was released it might happen that the ref is reused, but it's better to assume they aren't the same variable.

        DB<8> for my $x (1..3) { print \$x } SCALAR(0x3450e50)SCALAR(0x3450e50)SCALAR(0x3450e50) DB<9> for my $x (1..2) { print \$x; $a = sub {$x} } SCALAR(0x3459b20)SCALAR(0x3328238)

        $x has different refs in line 9 because the first $x is captured in a closure and not relased.

        Hence Perl can't reuse the reference.

        HTH! :)

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Log In?
Username:
Password:

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

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

    No recent polls found