in reply to Re^3: How do closures and variable scope (my,our,local) interact in perl?
in thread How do closures and variable scope (my,our,local) interact in perl?

Perhaps we are just going in word circles here, but it seems to me that an enclosed global does in fact get whatever happens to be the localized value of its current context. In this example below, the sub is defined in the outer block, but when it runs in a block where $x is localized, it uses the localized value, not the value from the outer block.

my @colors=qw(red blue green yellow orange purple violet); print "----- our \$x; for \$x ...; after for block ---------\n"; our $x; foreach $x (@colors) { no strict 'refs'; my $name=$x; *{$x.'_0'}=sub { $x="$x|$x"; print "doubling \$x: <$x>\n"; }; } print "setting \$x to 'x'\n"; $x="x"; red_0(); { local $x="X"; print "localized \$x to 'X'\n"; red_0(); print "leaving localization block\n"; } red_0();

prints out

----- our $x; for $x ...; after for block --------- setting $x to 'x' doubling $x: <x|x> localized $x to 'X' doubling $x: <X|X> leaving localization block doubling $x: <x|x|x|x>

But maybe what you are trying to say is that the way I talked about "localization" indicates a misunderstanding? I was thinking that localization "overlay" the variable with a new variable, but it seems that you are saying that it doesn't do that at all: rather it shoves the current value off into a side area, sets a new value, and the copies the old value back at the end of the block. Do I have that right?

As for the troubling difference, I suppose I think of file scope my variables as the "same kind" of variable as "our" variables, just private to a file. My guess is that you do not - for one - there are some major differences: our variables can be localized; my variables, even file scope my variables, cannot.

All the same, outside of the for loop I expect anything associated with file scope $x to have the value assigned to file scope $x. But that is not what happens. Consider what happens if we use my $x; for $x.... In this case, running the sub after the for block is not affected at *all* by the current value of $x, even though $x was declared as a file scope lexical. It does, however, make and pick up changes to @colors as this code and output shows:

my @colors=qw(red blue green yellow orange purple violet); print "----- my \$x; for \$x ... ---------\n"; my $x; foreach $x (@colors) { no strict 'refs'; my $name=$x; *{$x.'_0'}=sub { $x="$x|$x"; print "doubling \$x: <$x>\n"; }; } $x="x"; print "set \$x to 'x'\n"; print "\$colors[0]=<$colors[0]> \$x=<$x>\n"; red_0(); print "\$colors[0]=<$colors[0]> \$x=<$x>\n"; $colors[0]='RED'; print "setting \$colors[0] to 'RED'\n"; red_0();

outputs

----- my $x; for $x ... --------- set $x to 'x' $colors[0]=<red> $x=<x> doubling $x: <red|red> $colors[0]=<red|red> $x=<x> setting $colors[0] to 'RED' doubling $x: <RED|RED> doubling $x: <RED|RED|RED|RED>

In other words, when captured by a closure, the our variable loses its aliased association outside of the for loop, the file scope my variable does not [ inside the closure ].

Best, beth

Update: clarification in square brackets. As ikegami point out below, my $x not in the closure does in fact lose its aliasing.

Replies are listed 'Best First'.
Re^5: How do closures and variable scope (my,our,local) interact in perl?
by ikegami (Patriarch) on Jun 16, 2009 at 19:43 UTC

    Your code shows is that it prints the current value of $main::x, as set using = or by local restoring the backed up value.

    it seems to me that an enclosed global does in fact get whatever happens to be the localized value of its current context.

    I have no idea what that means. "Enclosed global" is a contradiction. Values aren't localised, variables are. (It backups up their value and restores it later.)

    when it runs in a block where $x is localized, it uses the localized value, not the value from the outer block.

    Again, "localised value" makes no sense.

    The "when" is misleading. There's nothing conditional about it. The same would apply if it wasn't localised. The whole sentence could be replaced with "It uses the current value".

    I was thinking that localization "overlay" the variable with a new variable,

    Localisation

    1. Backups the variable (to be restored on scope exit).
    2. Creates a new SV.
    3. Aliases the variable to that SV.

    But it's still the same variable. Any change to the variable will be seen globally.

    $y = 123; sub f { print("$y\n"); } # 456 { local $y = 456; f(); } # Same var

    That differs from my which actually creates a new var.

    my $x = 123; sub f { print("$x\n"); } # 123 { my $x = 456; f(); } # Different var
Re^5: How do closures and variable scope (my,our,local) interact in perl?
by ikegami (Patriarch) on Jun 16, 2009 at 20:03 UTC
    [ The parent post initially ended at "Do I have that right?". This addresses the second half ]

    As for the troubling difference, I suppose I think of file scope my variables as the "same kind" of variable as "our" variables, just private to a file.

    There's nothing special about the file scope. It's just like every other scope. All the differences between lex and pkg vars (access, ability to capture, lifespan, etc) exist whether they are in a block or nested deeper.

    All the same, outside of the for loop I expect anything associated with file scope $x to have the value assigned to file scope $x. But that is not what happens.

    I explained what happens here.

    In short, when you capture, you link to the SV associated with the captured name. Since foreach loops change which SV is associated with the iterator each pass of the loop ("aliasing"), you capture something different every pass of the loop.

    when captured by a closure, the our variable loses its aliased association outside of the for loop, the file scope my variable does not.

    The last bit is wrong. It does indeed lose its aliasing (and localisation).

    my $y = 5; my $x; for $x ($y) { ++$x; print "$y\n"; # 6 } ++$x; print "$y\n"; # 6

    For package variables, the name is captured. The SV is looked up in the symbol table. If a different SV is later associated with the captured variable, that SV will be used.

    For lexical variables, the SV is captured. If a different SV is later associated with the captured variable, the will not be closure won't know about it.