$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
| [reply] [d/l] [select] |
(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:
- Why are there five keys in the hash, for eight apparently different expressions?
- Which of the key definitions don't cause function f to be called in the second example?
- Why is there a different value for $h{'f'}?
- Why is there an odd number of calls to the function f in both examples?
- Where do the keys -1, 1, and 1.0 come from?
I always wanted to test that Perlmonks' spoiler element, so here it is:
- Why are there five keys in the hash, for eight apparently different expressions?
-> Both -f and - f evaluate to the string '-f' which I found slightly surprising. Also, as pointed out by haukex, +f, + f and f() all evaluate to the same function call. So we've lost three values. But wait: Should't -f() and - f() also yield the same key? Well, they don't, but this isn't related to the bareword stuff so we're getting to this later.
- Which of the key definitions don't cause function f to be called in the second example?
-> I wouldn't have known this and wouldn't have used this anyway, but obviously +f and + f both return a key of 'f' instead of calling the function. So they also fail to provide "new" keys, and the hash ends up with the same five keys as in the first example. Probably this is even documented somewhere.
- Why is there a different value for $h{'f'}?
-> See the previous answer. The keys +f and + f both return a plain key 'f', so the last of these assignments wins, setting the value to '+ F'. In the first example, +f and + f call the function f(), so the original value $h{'f'} = ' F' survives.
- Why is there an odd number of calls to the function f in both examples?
-> This one has nothing to do with stringification, but touches the topic of builtins interfering, unexpectedly for the unwary (like me). Clearly, all expressions containing parentheses call something. But while - f() calls the function as expected, -f() calls the builtin -f file test function. This is why I have provided some value for $_ - otherwise the code complains about Use of uninitialized value $_ in -f at /tmp/d.pl line 8.
- Where do the keys -1, 1, and 1.0 come from?
-> This should be rather obvious from the previous explanations. 1.0 is the plain return value from function f(). -1 is the result of calling -f(), which is converted to numeric and hence has lost the decimal point. Finally, 1 is the result of calling the -f() file test with no parameters, so $_ is used, which holds the path to the running program $0. I added '.0' to the return value of my own f() just to make these two cases distinguishable.
| [reply] [d/l] [select] |