Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Deparse says \my(%hash) is the same as \my %hash but it isn't

by Anonymous Monk
on Nov 21, 2012 at 11:07 UTC ( #1004902=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Deparse says \my(%hash) is the same as \my %hash but it isn't

$ perl - warn \my %hash; warn \my(%hash); ^Z HASH(0x99aa14) at - line 1. Warning: something's wrong at - line 2. $ perl -MO=Deparse - warn \my %hash; warn \my(%hash); ^Z warn \my(%hash); warn \(my(%hash)); - syntax OK

Maybe I'm not remembering correctly, but I thought Deparse had it right, not this

$ perl -le " warn scalar(\my %hash)" HASH(0x99aa34) at -e line 1. $ perl -le " warn scalar(\my(%hash))" SCALAR(0x3f4788) at -e line 1. $ perl -MData::Dump -le " dd scalar(\my(%hash))" \undef

Comment on Deparse says \my(%hash) is the same as \my %hash but it isn't
Select or Download Code
Re: Deparse says \my(%hash) is the same as \my %hash but it isn't
by Anonymous Monk on Nov 21, 2012 at 11:15 UTC

    Maybe this is more clear

    $ perl -MO=Deparse,-p - warn \my %hash; warn \my(%hash); ^Z warn((\my(%hash))); warn(\(my(%hash))); - syntax OK $ perl - warn((\my(%hash))); warn(\(my(%hash))); ^Z Warning: something's wrong at - line 1. Warning: something's wrong at - line 2.

    Any way you slice it you're not getting a reference from Deparse output

Re: Deparse says \my(%hash) is the same as \my %hash but it isn't
by Jenda (Abbot) on Nov 21, 2012 at 14:10 UTC

    How was the quote? You can't make shit up ... ?

    What's the code supposed to mean?

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

      How was the quote? You can't make shit up ... ? What's the code supposed to mean?

      It means you don't know jack :) its literally two lines, it doesn't warrant going all Jenda upon the OP

Re: Deparse says \my(%hash) is the same as \my %hash but it isn't
by Athanasius (Monsignor) on Nov 21, 2012 at 16:46 UTC

    If we begin by taking my out of the equation, and simplify by using an array rather than a hash, it’s easy to see the difference:

    23:10 >perl -Mstrict -wE "my @c = ('a' .. 'e'); my $q = \@c; my $r = \ +(@c); say $q, ' --> ', @$q, qq[\n], $r, ' --> ', $$r;" ARRAY(0x18a5654) --> abcde SCALAR(0x4bc344) --> e

    Whereas \@... evaluates as a reference to a variable, \(...) evaluates as a reference to the final value (a scalar) of the list within the parentheses.

    Does the same logic hold when my is reintroduced? It would appear so:

    1:46 >perl -Mstrict -wE "my $q = \my @c; @c = ('f' .. 'h'); say $q, +' --> ', @$q;" ARRAY(0x177554c) --> fgh 1:46 >perl -Mstrict -wE "my $q = \my(@c); @c = ('f' .. 'h'); say $q, +' --> ', $$q;" Use of uninitialized value in say at -e line 1. SCALAR(0x1d20f6c) --> 1:46 >

    Assigning to @c affects the contents of @$q, showing that \my @c not only declares @c as a lexical variable but also returns a reference to it. But \my(@c) declares @c as a lexical variable and then returns its contents as an empty list, with the result that the expression returns a reference to undef.

    Now to Deparse: The problem is not that it fails to distinguish between the two cases, since it clearly does: \my(%hash) and \(my(%hash)) are not the same. The problem becomes apparent if we add some labels:

    (a) \my %hash --> (b) \my(%hash) but (b) \my(%hash) --> (c) \(my(%hash))

    Deparse changes (a) into (b) but also changes (b) into (c). That is, running Deparse on its own output will produce a different result the second time around: (a) --> (b) --> (c). This certainly looks like a bug.

    The use of warn introduces another anomaly. Consider:

    1:11 >perl -wE "warn undef;" Use of uninitialized value in warn at -e line 1. Warning: something's wrong at -e line 1. 1:12 >perl -wE "warn \undef;" SCALAR(0x1d20f6c) at -e line 1. 1:12 >

    In the OP’s code, warn appears to be treating \my(%hash) as undef, and not as \undef, as would be expected. I don’t see the reason for this, either.

    Update: Thanks to tye for clearing up the behaviour of warn:

    Constructing a reference to each scalar in an empty list gives one an empty list of references, which is just an empty list.

    I had to read this several times before the lightbulb went on. Of course! There is no undef, only an empty list. I’d forgotten about context — the key point being, as tye says, that \( ... ) returns a list of references.

    Athanasius <°(((><contra mundum

      In the OPís code, warn appears to be treating \my(%hash) as undef, and not as \undef, as would be expected. I donít see the reason for this, either.

      \( ... ) returns a list of references, one reference for each item in the list. my(%hash) initializes %hash to be empty so, %hash in a list context gives the empty list. Constructing a reference to each scalar in an empty list gives one an empty list of references, which is just an empty list. warn treats an empty list the same as a list containing one (or more) undef(s). No mystery there (for me).

      As to the original question, it looks to me to just be a bug in Deparse.

      Now, I could see Perl deciding to go either way on whether \my(%hash) should be treated like \my %hash or like \(my %hash). My guess is that the current behavior was not a conscious choice but was more an accident of implementation details. So it would be conceivable to fix the Deparse bug by changing Perl to agree on this specific point. But that seems unlikely (surely p5p would argue that there might be code that already depends on the current behavior of \my(%hash), a point that I probably give much less weight to but that I agree with).

      I'm not going to dive into the Deparse source code to try to get an idea as to how complicated it might be to fix the deparsing of \my %hash (without breaking the deparsing of some other obscure use of 'my'). But I suggest the original poster report it as a bug in the module.

      - tye        

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1004902]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (16)
As of 2014-12-18 10:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (49 votes), past polls