(quickie) (Aliasing) Possible to get this to work in strict?

Discussion in 'Perl Misc' started by Crom, Dec 14, 2004.

  1. Crom

    Crom Guest

    1: my $n = 5;
    2: *r = \$n;
    3:
    4: $r++; # both should now be 6
    5: $n++; # both should not be 7
    6:
    7: print "\$n = $n\n\$r = $r";


    Works fine without 'use strict'...

    $n = 7
    $r = 7

    ....but with strict it barfs.

    Global symbol "$r" requires explicit package name at line 6.
    Global symbol "$r" requires explicit package name at line 9.
     
    Crom, Dec 14, 2004
    #1
    1. Advertising

  2. Also sprach Crom:

    > 1: my $n = 5;
    > 2: *r = \$n;
    > 3:
    > 4: $r++; # both should now be 6
    > 5: $n++; # both should not be 7
    > 6:
    > 7: print "\$n = $n\n\$r = $r";
    >
    >
    > Works fine without 'use strict'...
    >
    > $n = 7
    > $r = 7
    >
    > ...but with strict it barfs.
    >
    > Global symbol "$r" requires explicit package name at line 6.
    > Global symbol "$r" requires explicit package name at line 9.


    You can circumvent that by pre-declaring $r using our() or 'use vars':

    use strict;

    our $r; # pre-5.6.0 perls: use vars qw/$r/;
    my $n = 5;

    *r = \$n;
    $r++;
    print "$n - $r\n";
    __END__
    6 - 6

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Dec 14, 2004
    #2
    1. Advertising

  3. Crom

    Anno Siegel Guest

    Crom <> wrote in comp.lang.perl.misc:
    > 1: my $n = 5;
    > 2: *r = \$n;
    > 3:
    > 4: $r++; # both should now be 6
    > 5: $n++; # both should not be 7
    > 6:
    > 7: print "\$n = $n\n\$r = $r";
    >
    >
    > Works fine without 'use strict'...
    >
    > $n = 7
    > $r = 7
    >
    > ...but with strict it barfs.
    >
    > Global symbol "$r" requires explicit package name at line 6.
    > Global symbol "$r" requires explicit package name at line 9.


    "use strict" means, among other things, that you have to declare
    all variables. You haven't declared your variables, so it complains.

    Anno
     
    Anno Siegel, Dec 14, 2004
    #3
  4. On Tue, 14 Dec 2004 09:54:16 +0100, "Tassilo v. Parseval"
    <> wrote:

    >You can circumvent that by pre-declaring $r using our() or 'use vars':
    >
    > use strict;
    >
    > our $r; # pre-5.6.0 perls: use vars qw/$r/;
    > my $n = 5;
    >
    > *r = \$n;
    > $r++;
    > print "$n - $r\n";
    > __END__
    > 6 - 6


    Speaking of which, may I ask you to give an explanation of how this
    works internally? (Just curious...)

    What I mean is that we all know that Perl5 has basically two
    fundamentally orthogonal variable systems. And we know we can access
    directly a package's symbol table, but AFAIK we can't do the same with
    lexical variables, even though there "MUST" be one, and given the
    orthogonality hinted to above, it is somewhat surprising that such an
    aliasing can even be done. Oh, and of course on lexical scope exit it
    will "downgrade" to a simple copy, won't it? (Just tried, and AFAICT
    it is indeed so).

    Incidentally Perl6's planned solution to the variables' nature
    dichotomy by means of an inner layer of magic, namely that provided by
    the MY package, IMHO is very appealing, and I wonder wether it may
    eventually leak in some future Perl5 release...


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
     
    Michele Dondi, Dec 15, 2004
    #4
  5. Also sprach Michele Dondi:

    > On Tue, 14 Dec 2004 09:54:16 +0100, "Tassilo v. Parseval"
    ><> wrote:
    >
    >>You can circumvent that by pre-declaring $r using our() or 'use vars':
    >>
    >> use strict;
    >>
    >> our $r; # pre-5.6.0 perls: use vars qw/$r/;
    >> my $n = 5;
    >>
    >> *r = \$n;
    >> $r++;
    >> print "$n - $r\n";
    >> __END__
    >> 6 - 6

    >
    > Speaking of which, may I ask you to give an explanation of how this
    > works internally? (Just curious...)


    It probably means that on the inside just the pointer to the original
    variable is copied. On ordinary assignments, perl copies the C structure
    into a new variable. Here it just copies the memory address.

    > What I mean is that we all know that Perl5 has basically two
    > fundamentally orthogonal variable systems. And we know we can access
    > directly a package's symbol table, but AFAIK we can't do the same with
    > lexical variables, even though there "MUST" be one, and given the
    > orthogonality hinted to above, it is somewhat surprising that such an
    > aliasing can even be done. Oh, and of course on lexical scope exit it
    > will "downgrade" to a simple copy, won't it? (Just tried, and AFAICT
    > it is indeed so).


    No, an alias remains an alias. Perl increments the reference-count of
    the variable to be aliased:

    ethan@ethan:~$ perl -MDevel::peek
    { my $c = 42;
    Dump($c);
    *alias = \$c;
    Dump($alias);
    }
    Dump($alias);
    __END__
    SV = IV(0x8163094) at 0x814cc6c
    REFCNT = 1
    FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    IV = 42
    SV = IV(0x8163094) at 0x814cc6c
    REFCNT = 2
    FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    IV = 42
    SV = IV(0x8163094) at 0x814cc6c
    REFCNT = 1
    FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    IV = 42

    So after doing the aliasing, the reference-count has gone up to 2. On
    scope exist, it is decreased again by one. Since the reference-count
    hasn't yet gone to zero, the memory previously associated with 'my $c'
    remains intact and can still be accessed through the alias. Also note
    how the memory addresses involved are all identical. My suspicion is
    that aliases were just a side-effect that turned out to be very useful.
    It is the C-semantics of copying a pointer ported to perl.

    Aliases are a lot like hard links on Unices. You can delete the file
    that was hard-linked to but the hard link itself remains valid and
    behaves if it was the original file. Which it is anyway, from the point
    of view of the filesystem.

    As for lexical variables, technically they are not very different from
    package variables. They have the PADMY flag set which means they are
    subject to refcounting. Other than that, they only differ from package
    variables in that they are not kept in a symbol-table but in so called
    pads. Each block has its own pad and they are inaccessible from
    pure-Perl (unless someone writes an XS extension that makes them
    accessible).

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Dec 16, 2004
    #5
  6. "Tassilo v. Parseval" <> writes:
    > As for lexical variables, technically they are not very different from
    > package variables. They have the PADMY flag set which means they are
    > subject to refcounting. Other than that, they only differ from package
    > variables in that they are not kept in a symbol-table but in so called
    > pads. Each block has its own pad and they are inaccessible from
    > pure-Perl (unless someone writes an XS extension that makes them
    > accessible).


    Maybe I misunderstand the above, but it seems to say that in the code
    snippet below, the lexical variable $x should not be seen by the
    'eval' inside the block. But the output in the block is "r = 7" (while
    $y is 5, showing that the outer $x is unchanged), so 'eval' does see
    the lexical variable. What am I missing?

    $e = '$x';
    $x = 5;
    *y = $x;
    {
    my $x = 7;
    $r = eval $e;
    print "r = $r\n";
    print "outer r = $y\n";
    }
    $r = eval $e;
    print "r = $r\n";
     
    Arndt Jonasson, Dec 16, 2004
    #6
  7. Also sprach Arndt Jonasson:

    > "Tassilo v. Parseval" <> writes:
    >> As for lexical variables, technically they are not very different from
    >> package variables. They have the PADMY flag set which means they are
    >> subject to refcounting. Other than that, they only differ from package
    >> variables in that they are not kept in a symbol-table but in so called
    >> pads. Each block has its own pad and they are inaccessible from
    >> pure-Perl (unless someone writes an XS extension that makes them
    >> accessible).

    >
    > Maybe I misunderstand the above, but it seems to say that in the code
    > snippet below, the lexical variable $x should not be seen by the
    > 'eval' inside the block. But the output in the block is "r = 7" (while
    > $y is 5, showing that the outer $x is unchanged), so 'eval' does see
    > the lexical variable. What am I missing?


    Why should 'eval' not see lexical variables? It does see them. It sees
    the lexical $x here because inner lexicals override variables by that
    name in an outer block.

    > $e = '$x';
    > $x = 5;
    > *y = $x;


    Did you mean to write

    *y = \$x;

    here?

    > {
    > my $x = 7;
    > $r = eval $e;
    > print "r = $r\n";
    > print "outer r = $y\n";
    > }
    > $r = eval $e;
    > print "r = $r\n";


    With the change suggested above, I get:

    r = 7
    outer r = 5
    r = 5

    Is this not what you would expect?

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Dec 16, 2004
    #7
  8. "Tassilo v. Parseval" <> writes:
    > Also sprach Arndt Jonasson:
    >
    > > "Tassilo v. Parseval" <> writes:
    > >> As for lexical variables, technically they are not very different from
    > >> package variables. They have the PADMY flag set which means they are
    > >> subject to refcounting. Other than that, they only differ from package
    > >> variables in that they are not kept in a symbol-table but in so called
    > >> pads. Each block has its own pad and they are inaccessible from
    > >> pure-Perl (unless someone writes an XS extension that makes them
    > >> accessible).

    > >
    > > Maybe I misunderstand the above, but it seems to say that in the code
    > > snippet below, the lexical variable $x should not be seen by the
    > > 'eval' inside the block. But the output in the block is "r = 7" (while
    > > $y is 5, showing that the outer $x is unchanged), so 'eval' does see
    > > the lexical variable. What am I missing?

    >
    > Why should 'eval' not see lexical variables? It does see them. It sees
    > the lexical $x here because inner lexicals override variables by that
    > name in an outer block.
    >
    > > $e = '$x';
    > > $x = 5;
    > > *y = $x;

    >
    > Did you mean to write
    >
    > *y = \$x;
    >
    > here?


    Oops, yes. Or *y=*x. I made the last change in the test program but
    not in the article.

    > With the change suggested above, I get:
    >
    > r = 7
    > outer r = 5
    > r = 5
    >
    > Is this not what you would expect?


    It is, but "inaccessible from pure-Perl" made me think it might not
    work. Does "inaccessible" simply mean that there is no package hash
    table one can traverse to find the variable?
     
    Arndt Jonasson, Dec 16, 2004
    #8
  9. Crom

    Anno Siegel Guest

    Tassilo v. Parseval <> wrote in comp.lang.perl.misc:

    > Aliases are a lot like hard links on Unices. You can delete the file
    > that was hard-linked to but the hard link itself remains valid and
    > behaves if it was the original file. ...


    The analogy extends to the link count of a file, which has the same
    function and reason-of-being as the refcount of a Perl variable.

    Anno
     
    Anno Siegel, Dec 16, 2004
    #9
  10. Crom

    Peter Scott Guest

    In article <>,
    Arndt Jonasson <> writes:
    >"Tassilo v. Parseval" <> writes:
    >> Also sprach Arndt Jonasson:
    >>
    >> > "Tassilo v. Parseval" <> writes:
    >> >> As for lexical variables, technically they are not very different from
    >> >> package variables. They have the PADMY flag set which means they are
    >> >> subject to refcounting. Other than that, they only differ from package
    >> >> variables in that they are not kept in a symbol-table but in so called
    >> >> pads. Each block has its own pad and they are inaccessible from
    >> >> pure-Perl (unless someone writes an XS extension that makes them
    >> >> accessible).

    [snip]
    > "inaccessible from pure-Perl" made me think it might not
    >work. Does "inaccessible" simply mean that there is no package hash
    >table one can traverse to find the variable?


    Yes, but: http://search.cpan.org/~robin/PadWalker-0.10/PadWalker.pm

    --
    Peter Scott
    http://www.perldebugged.com/
    *** NEW *** http://www.perlmedic.com/
     
    Peter Scott, Dec 16, 2004
    #10
  11. On Thu, 16 Dec 2004 10:03:13 +0100, "Tassilo v. Parseval"
    <> wrote:

    >> aliasing can even be done. Oh, and of course on lexical scope exit it
    >> will "downgrade" to a simple copy, won't it? (Just tried, and AFAICT
    >> it is indeed so).

    >
    >No, an alias remains an alias. Perl increments the reference-count of
    >the variable to be aliased:


    Well, but from the UI-point of view, I mean: it acts in a way that is
    perfectly undistinguishable from a copy, doesn't it?

    > ethan@ethan:~$ perl -MDevel::peek
    > { my $c = 42;
    > Dump($c);
    > *alias = \$c;
    > Dump($alias);
    > }
    > Dump($alias);
    > __END__
    > SV = IV(0x8163094) at 0x814cc6c
    > REFCNT = 1
    > FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    > IV = 42
    > SV = IV(0x8163094) at 0x814cc6c
    > REFCNT = 2
    > FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    > IV = 42


    I see... but now that I think of it better, examining your example in
    detail, isn't it somewhat contradictory that the *package* variable
    $alias has the PADMY flag set, what that as you explain below should
    mark a lexical variable?


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
     
    Michele Dondi, Dec 17, 2004
    #11
  12. Also sprach Michele Dondi:

    > On Thu, 16 Dec 2004 10:03:13 +0100, "Tassilo v. Parseval"
    ><> wrote:
    >
    >>> aliasing can even be done. Oh, and of course on lexical scope exit it
    >>> will "downgrade" to a simple copy, won't it? (Just tried, and AFAICT
    >>> it is indeed so).

    >>
    >>No, an alias remains an alias. Perl increments the reference-count of
    >>the variable to be aliased:

    >
    > Well, but from the UI-point of view, I mean: it acts in a way that is
    > perfectly undistinguishable from a copy, doesn't it?


    Yes, quite. There's no way to tell the original from the alias.

    >> ethan@ethan:~$ perl -MDevel::peek
    >> { my $c = 42;
    >> Dump($c);
    >> *alias = \$c;
    >> Dump($alias);
    >> }
    >> Dump($alias);
    >> __END__
    >> SV = IV(0x8163094) at 0x814cc6c
    >> REFCNT = 1
    >> FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    >> IV = 42
    >> SV = IV(0x8163094) at 0x814cc6c
    >> REFCNT = 2
    >> FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    >> IV = 42

    >
    > I see... but now that I think of it better, examining your example in
    > detail, isn't it somewhat contradictory that the *package* variable
    > $alias has the PADMY flag set, what that as you explain below should
    > mark a lexical variable?


    In a way it seems like a contradiction. But on closer inspection it is
    not, because you created an alias to a lexical variable. And as there is
    no way to distinguish between original and alias (as said above), the
    alias must behave just as the original variable. And that includes
    refcounting, therefore PADMY.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Dec 17, 2004
    #12
  13. Also sprach Tassilo v. Parseval:

    > Also sprach Michele Dondi:
    >
    >> On Thu, 16 Dec 2004 10:03:13 +0100, "Tassilo v. Parseval"


    >>> ethan@ethan:~$ perl -MDevel::peek
    >>> { my $c = 42;
    >>> Dump($c);
    >>> *alias = \$c;
    >>> Dump($alias);
    >>> }
    >>> Dump($alias);
    >>> __END__
    >>> SV = IV(0x8163094) at 0x814cc6c
    >>> REFCNT = 1
    >>> FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    >>> IV = 42
    >>> SV = IV(0x8163094) at 0x814cc6c
    >>> REFCNT = 2
    >>> FLAGS = (PADBUSY,PADMY,IOK,pIOK)
    >>> IV = 42

    >>
    >> I see... but now that I think of it better, examining your example in
    >> detail, isn't it somewhat contradictory that the *package* variable
    >> $alias has the PADMY flag set, what that as you explain below should
    >> mark a lexical variable?

    >
    > In a way it seems like a contradiction. But on closer inspection it is
    > not, because you created an alias to a lexical variable. And as there is
    > no way to distinguish between original and alias (as said above), the
    > alias must behave just as the original variable. And that includes
    > refcounting, therefore PADMY.


    When thinking about that a little further, this explanation is
    misleading. It implies that perl would internally do additional work to
    ensure that both the original and the alias have the same flags. This is
    not the case. Perl merely copies the pointer to the original variable
    into the alias, and that is the explanation why even a package variable
    can have the flags of a lexical. This is easier to understand when
    looking at what happens on the C level (simplified):

    SV *lexical; /* gets initialized somewhere below */
    ...
    SV *alias = lexical;
    SvREFCNT_inc(lexical);

    'lexical' and 'alias' point to the same memory address in which all the
    flags, slots (such as IV, NV, PV, ...), refcount field etc. are stored.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Dec 17, 2004
    #13
  14. [A complimentary Cc of this posting was sent to
    Tassilo v. Parseval
    <>], who wrote in article <>:

    > In a way it seems like a contradiction. But on closer inspection it is
    > not, because you created an alias to a lexical variable. And as there is
    > no way to distinguish between original and alias (as said above), the
    > alias must behave just as the original variable. And that includes
    > refcounting, therefore PADMY.


    I do not see what PADMY has to do with refcounting. AFAIK, it is used
    (after compilation) for one purpose only: optimization of $a = $b + $c
    if $a is lexical; in this case op_add() (sp?) can write to $a directly
    instead of writing to a temporary, then copying from a temporary to
    $a.

    And this is most probably done at compile time only...

    Hope this helps,
    Ilya
     
    Ilya Zakharevich, Dec 17, 2004
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bryan Parkoff

    Strict Pointer Aliasing Question

    Bryan Parkoff, Jan 14, 2004, in forum: C++
    Replies:
    2
    Views:
    1,266
    tom_usenet
    Jan 15, 2004
  2. Replies:
    20
    Views:
    954
    Netocrat
    Oct 24, 2005
  3. David Mathog
    Replies:
    3
    Views:
    744
    Chris Torek
    Jul 5, 2007
  4. Squat'n Dive
    Replies:
    3
    Views:
    307
    Martin v. Löwis
    Jan 17, 2008
  5. Paul Brettschneider

    char and strict aliasing

    Paul Brettschneider, Jul 17, 2008, in forum: C++
    Replies:
    4
    Views:
    455
    James Kanze
    Jul 18, 2008
Loading...

Share This Page