in reply to Re^2: Closures & aliases
in thread Closures & aliases

The nub of the problem is that most people expect that in the following code,
my $x = 1; sub foo { $x }
There is a single variable called $x which is accessible from the main program and from within foo. The way it happens to be implemented internally is that they are treated as two separate variables that happen to be initially aliased to the same value. Here's a little ASCII diagram.

Before the for loop; the two X's point to the same value

$MAIN_X --- \ -> +---+ $FOO_X ------> | 1 | +---+
and during for $x (9) { ...
+---+ $MAIN_X -----> | 9 | +---+ +---+ $FOO_X ------> | 1 | +---+
So calling foo from within the loop causes the 1 to be printed, not the 9.

You are mostly right about how localization and for aliasing work, expect that its not entire values that are temporarily saved, it is simply a C pointer, either in the symbol table (eg local $x), in the scratchpad (eg my $x; for $x ()), or in an array or hash slot (eg local $h{foo}), that is pushed onto perl's savestack and replaced with a pointer to a different value.

Dave.

Replies are listed 'Best First'.
Re^4: Closures & aliases
by ambrus (Abbot) on Jun 07, 2004 at 19:40 UTC

    I see.

    So, with global variables, like in

    $a = 2; sub f { print $a; } { local $a = 5; f; }'
    or
    $a = 2; sub f { print $a; } for $a (5) { f; }
    we get 5 as the result, as perl localizes $a dynamically.

    However, if you put my before $a, perl can not localize the variable dynamically. In the first case, local raises an error, as Larry knows Perl can't localize a my, so he explicitly denied it. In the second case, however, if you put my before $a in the beginning, for will not carp (that would be a too bad restriction), but instead localizes $a in the wrong way.