Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re^4: Hard syntax error or disambiguable parsing?

by ack (Deacon)
on Jan 29, 2009 at 16:44 UTC ( [id://739963]=note: print w/replies, xml ) Need Help??


in reply to Re^3: Hard syntax error or disambiguable parsing?
in thread Hard syntax error or disambiguable parsing?

Case 4 is in fact identical to case 3, since $v in both cases is already a 'my' variable, subject to lexical scoping.

That doesn't make sense to me. If anything, if I understand the documentation, Case 2 and 3 are almost identical and Cases 1 and 4 are almost identical.

In Cases 1 and 2, there is no indication about whether the outer, enclosing scope (outside of the scope of the foreach loop) there is any variable $v wandering around. Since it is not shown, I would presume that the intent is that no such varible exists in exterior scope(s). And I'm not sure that it really matters, in the context of what I'm thinking.

But, if I understand the documentation, in Cases 1 and 4, the use of my in the creation of the loop variable results in a lexically scoped variable and it never appears in any package symbol table.

However, in the situations in Cases 2 and 3, the loop variable is created as if it were created with a local construct. In which case the $v exists in the package symbol table, but a copy is created and used within the scope of the loop and the original value of $v is not touched. At the end of the loop's scope, the original value of $v is restored to the variable in the package symbol table.

So the difference, it seems to me, is whether the package symbol table's variables (symbols?) are used or a new, unseen (by the package symbol table) variable (symbol?) are created for the duration of the loop's scope.

For me, that would seem to make Cases 2 & 3 almost identical and Cases 1 & 4 almost identical.

But then, I'm still learning and could be wrong.

ack Albuquerque, NM

Replies are listed 'Best First'.
Re^5: Hard syntax error or disambiguable parsing?
by shmem (Chancellor) on Jan 29, 2009 at 21:32 UTC

    Cases 1, 3 and 4 are almost identical wrt the scoping rules applied to the loop variable. Case 1 differs to the others only in that the lexical variable $v doesn't exist before the perl compiler sees the loop (so I guess that $v will be allocated in that scope's scratchpad.)

    Case 2 is the only different one wrt to scoping - depending on whether $v has been declared outside the scope in which the foreach occurs at all, or declared as my, or as our:

    • if it hasn't been declared, $v will mask a package variable,
    • which is also the case if $v has been declared with our;
    • if it has been declared with my, the loop variable will be aliasing that $v, and lexically scoped - in that case, the scoping rules are identical to 1, 3 and 4.

    See also Re^6: Hard syntax error or disambiguable parsing?.

      if it has been declared with my, the loop variable will be aliasing that $v, and lexically scoped

      What, exactly, does 'aliasing that $v' mean?

      I expect it means the same thing as 'it uses that variable instead of the global one' in the following extract from perlsyn, but I don't know what that means either.

      If the variable was previously declared with my, it uses that variable instead of the global one, but it's still localized to the loop.

      I thought I knew what it meant but the examples here prove that my (mis-)understanding was wrong. What is the significance of it using that variable? When does it make a difference?

      Based on the examples here, it seems as if perlsyn could (maybe should) be rewritten to say:

      If the variable was previously declared with my then the variable is implicitly lexically scoped, and is therefore visible only within the loop.

      Does this make sense? Is it correct? Or am I still ignorant and confused?

        I think the way it came about it that the foreach version of for each requires that the loop variable be aliased to the items in the list, and (at least historically) Perl's aliasing is achieved through globs.

        So, pre-lexicals, the localisation was done by doing local *loopvar; under the covers.

        Once lexicals came to pass, the quick fix for dealing with aliasing a lexical was to do the (rough?) equivalent of:

        $_ = 'fred'; my $i = 123; { local *_ = \$i; for $i ( 1 .. 5 ) { print $i; } } print "\$_:$_ \$i:$i" 1 2 3 4 5 $_:fred $i:123

        Which use *_ as the glob (per an implicit loop var loop), but allows the programmer to refer to the temporary variable by name within the loop body, whilst ensuring that both *_ and $i get restored afterward.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        There's surely somebody out there, who wrote the code, and could explain it better... ;-)

        Aliasing means, that the carcass of the variable is retained (its content saved to be restored later) and filled with a new structure, i.e. it gets a new pointer. Let's have a look. Loop with a symbol table variable:

        perl -MDevel::Peek -le 'our $f = 42; Dump *f{SCALAR}; for $f (2) { Dum +p *f{SCALAR} }' SV = RV(0x8664670) at 0x863bc28 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x863c7bc SV = IV(0x8657eec) at 0x863c7bc REFCNT = 2 FLAGS = (IOK,pIOK) IV = 42 SV = RV(0x8664670) at 0x863be2c REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x863c7ec SV = IV(0x8657ee8) at 0x863c7ec REFCNT = 3 FLAGS = (PADBUSY,PADTMP,IOK,READONLY,pIOK) IV = 2

        Note that the scalar variable (SV) contains the same reference value (RV(0x8664670)) outside and inside the loop. It's content however is allocated at a different memory location:

        SV = RV(0x8664670) at 0x863bc28 # outside SV = RV(0x8664670) at 0x863be2c # inside

        That's essentially the same for my variables.

        perl -MDevel::Peek -le 'my $f = 42; Dump \$f; for $f (2) { Dump \$f } +for my $f (2) { Dump \$f }' SV = RV(0x9d1a678) at 0x9cf1c28 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x9cf1cdc SV = IV(0x9d0def8) at 0x9cf1cdc REFCNT = 2 FLAGS = (PADBUSY,PADMY,IOK,pIOK) IV = 42 SV = RV(0x9d1a678) at 0x9cf1e2c REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x9cf1c28 SV = IV(0x9d0defc) at 0x9cf1c28 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 2 SV = RV(0x9d1a678) at 0x9cf1c28 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x9cf1e2c SV = IV(0x9d0defc) at 0x9cf1e2c REFCNT = 1 FLAGS = (IOK,pIOK) IV = 2

        Here we have three different storage locations, because the two loops have each its own scope:

        SV = RV(0x9d1a678) at 0x9cf1c28 SV = RV(0x9d1a678) at 0x9cf1e2c SV = RV(0x9d1a678) at 0x9cf1c28

        The RV(0x9d1a678) is the same, which shows us that the following for loops are aliasing the same $f :

        my $f; for $f (1..3) { } for my $f (1..3) { }

        In the perl sources, you'll find the relevant code which sets up the loop variable at Perl_newFOROP() in file op.c, and the "aliasing code" in pp_ctl.c at PP(pp_enteriter).

        update: corrected code locations

        What, exactly, does 'aliasing that $v' mean?

        This may not be what you're asking, but... the mechanics of "aliasing" fall out of the way Perl manages values.

        The name $s refers to a pointer to the value currently associated with that name. The array entry for $a[78] also refers to a pointer to the value currently associated with the entry. And so on. All values are accessed via one level of indirection.

        To make $v into an alias for some array entry, Perl simply copies the array entry's pointer to $v's pointer... shazzam ! (Which would probably be curtains for the old value associated with $v, "garbage collection"-wise; but that's another story.)

        Problem is clearly that on loop exit, left to its own devices, the loop variable would remain an alias -- aliases are magic enough when contained within the scope of the loop !

        I now speculate: I suspect that the $v doesn't know it's an alias, the mechanism is so deeply buried in the way variables work -- but in any case, extra code would be required to copy the last value to $v. Besides, much of the time it's useful to have a local loop variable, and since that mechanism already existed my guess would be that looked like the simplest approach...

        What is the significance of it using that variable? When does it make a difference?

        The difference is that if there is a Global and a Lexical $i in existence at the same time, then it is the Lexical that is localized for the duration of the loop. As this illustrates:

        use strict ; use warnings ; use vars '$i' ; $i = 'hello there' ; for $i (1..2) { print "$i: $main::i\n" ; # 1: 1 } ; # 2: 2 print "$i\n" ; # hello there for my $i (4..5) { print "$i: $main::i\n" ; # 4: hello there } ; # 5: hello there print "$i\n" ; # hello there my $i = '*' ; for $i (7..8) { print "$i: $main::i\n" ; # 7: hello there } ; # 8: hello there print "$i: $main::i\n" ; # *: hello there
        I suppose it might have been clearer if my at the package layer declared package variables... but that horse left home at some speed many, many moons ago.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (7)
As of 2024-04-19 06:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found