in reply to Re: Problem with perlcritic when using Moose object
in thread Problem with perlcritic when using Moose object

The Perl parser could confuse the bareword shift in the braces with its core function shift instead of converting it to a string.

I'm pretty sure that Perl will always take $hash{shift} to mean the hash key "shift", although adding any other characters will change that ($hash{+shift}, $hash{shift()}, etc.) See also.

Replies are listed 'Best First'.
Re^3: Problem with perlcritic when using Moose object
by haj (Vicar) on Oct 06, 2018 at 09:29 UTC
    I'm pretty sure that Perl will always take $hash{shift} to mean the hash key "shift", although adding any other characters will change that ($hash{+shift}, $hash{shift()}, etc.)

    I guess you're right. I've posted from memory because I thought that I had been bitten by something like that in the past. However, I failed to find any evidence, nor could I construct any test supporting my case. Quite on the contrary, I found that some other characters won't even prevent stringification, as is demonstrated by Tk's habit of having $hashref->{-option} reliably interpreted as $hashref->{'-option'}.

    Thanks for the correction!

      $hashref->{-option} reliably interpreted as $hashref->{'-option'}

      Interestingly, the former is actually interpreted as an expression (note the "negate" below), but the because of the properties of unary -, -bareword is the same as "-bareword". As of v5.26, "Bareword constant strings are now permitted to take part in constant folding."

      $ perlbrew exec --with 5.24.4,5.26.2 perl -MO=Concise -wMstrict -e 'my + %hash; print $hash{-foo}' perl-5.24.4 ========== b <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 2 -e:1) v:*,&,{,x*,x&,x$,$ ->3 3 <0> padhv[%hash:2,3] vM/LVINTRO ->4 4 <;> nextstate(main 3 -e:1) v:*,&,{,x*,x&,x$,$ ->5 a <@> print vK ->b 5 <0> pushmark s ->6 9 <2> helem sK/2 ->a 6 <0> padhv[%hash:2,3] sR ->7 8 <1> negate[t2] sK/1 ->9 7 <$> const(PV "foo") s/BARE ->8 -e syntax OK perl-5.26.2 ========== 8 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 2 -e:1) v:*,&,{,x*,x&,x$,$ ->3 3 <0> padhv[%hash:2,3] vM/LVINTRO ->4 4 <;> nextstate(main 3 -e:1) v:*,&,{,x*,x&,x$,$ ->5 7 <@> print vK ->8 5 <0> pushmark s ->6 - <1> ex-helem sK/2 ->7 6 <+> multideref($hash{"-foo"}) sK ->7 - <0> ex-padhv sR ->6 -e syntax OK
        (regarding $hashref->{-option})
        Interestingly, the former is actually interpreted as an expression (note the "negate" below),...

        Thanks for providing another interesting insight!

        We've moved pretty far from the original issue, so I've modified the title... and I allow myself to add some stuff I found while experimenting with bareword stringification (and, just for fun, abusing some not directly related pitfalls into which I fell some time ago). Warning: This isn't to be taken too seriously. Read on at your own risk.

        Consider the following code:

        use strict; use warnings; use Data::Dump qw(dump); $_ = $0; my %h; sub f { print('->f()') . '.0'; } $h{ f } = ' F'; $h{ +f } = ' +F'; $h{+ f } = '+ F'; $h{ -f } = ' -F'; $h{- f } = '- F'; $h{ f()} = ' ()'; $h{ -f()} = '-()'; $h{- f()} = '-()'; $h{ +f()} = '+()'; print "\n",dump(\%h),"\n";
        This prints:
        ->f()->f()->f()->f()->f() { "-1" => "-()", "-f" => "- F", "1" => "-()", "1.0" => "+()", "f" => " + F" }

        The resulting hash %h has five keys, and the function f has been called five times. Before going into the boring stuff, see the following code, which is equivalent... well, almost:

        use strict; use warnings; use Data::Dump qw(dump); $_ = $0; sub f { print('->f()') . '.0'; } my %h = ( f => ' F', +f => ' +F', + f => '+ F', -f => ' -F', - f => '- F', f() => ' ()', -f() => '-()', - f() => '-()', +f() => '+()', ); print "\n",dump(\%h),"\n";
        ...which prints...
        ->f()->f()->f() { "-1" => "-()", "-f" => "- F", "1" => "-()", "1.0" => "+()", "f" => " ++ F" }

        This time I've used "fat comma" stringification which got me the same keys, but only three calls to function f.

        So, these are the questions:

        1. Why are there five keys in the hash, for eight apparently different expressions?
        2. Which of the key definitions don't cause function f to be called in the second example?
        3. Why is there a different value for $h{'f'}?
        4. Why is there an odd number of calls to the function f in both examples?
        5. Where do the keys -1, 1, and 1.0 come from?

        I always wanted to test that Perlmonks' spoiler element, so here it is: