http://www.perlmonks.org?node_id=243024


in reply to Re: Lexical scoping like a fox
in thread Lexical scoping like a fox

Maybe it would be easier to express the distinction as spatial versus temporal scoping, which is an approach that I think makes sense at least until you start throwing threads and processes into the mix.

Let's take this example:

print "Just before start of scope\n"; { print "Just after start of scope\n"; my $a = 1; local $b = 1; print "a=$a, b=$b\n"; foo(); print "Just before end of scope\n"; } print "Just after end of scope\n";

Now, in this example, the line 'my $a = 1;' introduces a lexical variable. Any reference to $a in the statements following that introduction until the end of the scope refer to this newly introduced variable - and only those lines. This is a spatial scope: if the foo subroutine refers to a $a variable, it won't see this $a, because foo is not defined within this scope.

The line 'local $b = 1;' introduces a localisation - it tells the interpreter to save the current copy of the (package) variable $b, to be restored when execution reaches the end of the scope. Now it is a matter of time: after this localisation has been executed, anyone that looks at this package variable $b before the end of this scope is reached will see the localised version. If the foo subroutine refers to the package variable $b, it will see the localised version (for this call, at least).

Does that help at all?

Hugo

Replies are listed 'Best First'.
Re^3: Lexical scoping like a fox
by convenientstore (Pilgrim) on Jan 13, 2008 at 16:26 UTC
    Excellent tutorial for me(newbie)
    and yes Hugo, your example made it clear for me as I wrote out your example
    use strict; sub foo { print "\$a is ", defined($a) ? $a : 'undef', $/; print "\$b is ", defined($b) ? $b : 'undef', $/; } print "Just before start of scope\n"; { print "Just after start of scope\n"; my $a = 1; local $b = 1; print "a=$a, b=$b\n"; foo(); print "Just before end of scope\n"; } print "Just after end of scope\n"; print "\$a is ", defined($a) ? $a : 'undef', $/; print "\$b is ", defined($b) ? $b : 'undef', $/;
    Couple other questions/comments
    1)using input record separator as newline indicator is very interesting. Never seen it before but works well. Any reason?
    I am assuming it's just a style issue?
    2)Below code from tutorial does not work when I insert my next to variable.. can someone explain this?
    [root@myserver tmp]# cat -n !$ cat -n ./per_begin.pl1 1 #!/usr/bin/perl -w 2 3 use strict; 4 5 6 my $x = "original state"; 7 8 sub foo { 9 print " \$x is: $x\n"; 10 } 11 12 { # beginning of lexical scope 13 14 local $x = "altered state"; 15 foo(); 16 17 } # end of lexical scope 18 print "\$x is: $x\n"; [root@myserver tmp]# ./!$ ././per_begin.pl1 Can't localize lexical variable $x at ././per_begin.pl1 line 14.
    3)can someone explain further on "lexical variables are declared at compile-time, not initialised?
    Is this because BEGIN runs during compile-time? I sneaked in a new my $foo = something inside of BEGIN
    block and execution of the code came out w/ foo is something during BEGIN phase
      1)using input record separator as newline indicator is very interesting. Never seen it before but works well. Any reason? I am assuming it's just a style issue?

      I guess it's more along "a \n is a \n is a \n" - $/ is a global, and that could be changed far away without you knowing it; so it's more safety than style.

      2)Below code from tutorial does not work when I insert my next to variable.. can someone explain this?

      You are allocating a lexical $x, not a package global (which would be either use vars '$x' or our $x), and local aliases only package globals. You can't (shouldn't) allocate globs and lexicals of the same name in the same scope:

      our $x; my $x; # gives a warning
      our $x; { my $x; # ok }
      3)can someone explain further on "lexical variables are declared at compile-time, not initialised? Is this because BEGIN runs during compile-time? I sneaked in a new my $foo = something inside of BEGIN block and execution of the code came out w/ foo is something during BEGIN phase

      "lexical variables are declared at compile-time, not initialised" means "the container is created, but nothing is put into it". The initialization (= puting something into the bucket) happens at run time. BEGIN blocks are compiled and immediately run, that's why "code came out w/ foo is something during BEGIN phase".

      See also my/local, space/time (was: Re: The difference between my and local).

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      3)can someone explain further on "lexical variables are declared at compile-time, not initialised?

      It's the difference between "existing but having an undefined value (what you get when a variable is declared but not initialized -- ie. defined($var) returns false) vs. "existing with a defined value (what you get when you declare and initialize).