in reply to Using an "outer" lexical in a sub?

Perl doesn't really make a distinction between "normal" blocks and subroutine blocks with regard to lexical scoping rules. You can even take and copy a reference to a subroutine that accesses lexicals in its outer scope that way. This is by design. See also perlfaq7 (what's a closure?), perlsub and perlref.

use strict; sub make_ref { my $name = shift; my $i = 99; return sub { print "ref $name: ",$i++,"\n"; } } my $ref1 = make_ref("sub1"); my $ref2 = make_ref("sub2"); for (1 .. 10) { $ref1->(); $ref2->() if $_ % 2 == 0; }
output:
ref sub1: 99 ref sub1: 100 ref sub2: 99 ref sub1: 101 ref sub1: 102 ref sub2: 100 ref sub1: 103 ref sub1: 104 ref sub2: 101 ref sub1: 105 ref sub1: 106 ref sub2: 102 ref sub1: 107 ref sub1: 108 ref sub2: 103

Replies are listed 'Best First'.
Re^2: Using an "outer" lexical in a sub?
by cornballer (Novice) on Nov 01, 2006 at 21:03 UTC

    Very interesting... each copy of that referenced subroutine which gets returned by make_ref() gets its own "freeze-dried" copy of $i...

    I've got some reading to do. Thank you, and thanks also for the link to perlfaq7.

Re^2: Using an "outer" lexical in a sub?
by cornballer (Novice) on Nov 01, 2006 at 21:51 UTC
    Hm... I just tried something which, to me, looks like it should behave the same as the above code, but it won't do the same trick:
    #!/usr/bin/perl use strict; use warnings; my $ref1; my $ref2; { my $n = 10; $ref1 = sub { print( $n++, "\n" ) }; $ref2 = sub { print( $n++, "\n" ) }; } $ref1->(); # --> 10 $ref1->(); # --> 11 $ref1->(); # --> 12 print "\n"; $ref2->(); # --> 13 Huh? $ref2->(); # --> 14 ? $ref2->(); # --> 15 ?

    I'd expect that first call to $ref2->(); to start up with its own squirreled-away $n (starting at 10). Why doesn't it?

      It doesn't start with it's own version of $n, because at the time you're creating $ref1 and $ref2 $n is the same variable.

      You can look at it like this:

      sub test() { my $n = 10; { print( $n++, "\n" ) } { print( $n++, "\n" ) } print "\$n is now $n\n; }
      Now, you can see that both blocks access the same variable (i.e. $n will be 12 at the end of test()).

      If you run test() again, my $n = 10; will effectively be a new variable $n but if you still have a subref somewhere that accesses the old $n (i.e. a reference to a to one or more of the inner blocks) that code ref will hang on to its variables and new ones will be created if necessary.

      Note that in my earlier post the outer subroutine is called twice and that will create the new lexical variable.

        It doesn't start with it's own version of $n, because at the time you're creating $ref1 and $ref2 $n is the same variable.

        Doh! Thanks Joost (and imp). :)

        #!/usr/bin/perl use strict; use warnings; my $ref1; my $ref2; { my $n = 10; $ref1 = sub { print( $n++, "\n" ) }; } { my $n = 10; $ref2 = sub { print( $n++, "\n" ) }; } $ref1->(); # --> 10 $ref1->(); # --> 11 $ref1->(); # --> 12 print "\n"; $ref2->(); # --> 10 $ref2->(); # --> 11 $ref2->(); # --> 12
      { my $n = 10; $ref1 = sub { print( $n++, "\n" ) }; $ref2 = sub { print( $n++, "\n" ) }; }
      When the anonymous subroutine that is stored in $ref1 is created it increases the reference count for that instance of $n to 2.

      When the anonymous subroutine that is stored in $ref2 is created it increases the reference count for that instance of $n to 3.

      The two anonymous subroutines share the same $n in this case.