Neither, looks like undefined behaviour if you ask me :) JOKING
Yup, looks like a bug if you ask me
$ perl -e " $a{0} ||= scalar keys %a; print $a{0} "
1
$ perl -e " $a{0} += scalar keys %a; print $a{0} "
1
$ perl -e " $a{0} = $a{0}+ scalar keys %a; print $a{0} "
0
$ perl -e " $a{0} = $a{0} || scalar keys %a; print $a{0} "
0
$ perl -MO=Concise -e " $a{0} ||= scalar keys %a; print $a{0} "
j <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- <1> null vK/1 ->c
7 <|> orassign(other->8) vK/1 ->c
6 <2> helem sKRM/2 ->7
4 <1> rv2hv sKR/1 ->5
3 <#> gv[*a] s ->4
5 <$> const[PV "0"] s ->6
b <1> sassign sK/BKWARD,1 ->c
- <1> scalar sK/1 ->b
a <1> keys[t4] sK/1 ->b
9 <1> rv2hv[t3] lKRM/1 ->a
8 <#> gv[*a] s ->9
c <;> nextstate(main 1 -e:1) v:{ ->d
i <@> print vK ->j
d <0> pushmark s ->e
h <2> helem sK/2 ->i
f <1> rv2hv sKR/1 ->g
e <#> gv[*a] s ->f
g <$> const[PV "0"] s ->h
-e syntax OK
| $ perl -MO=Concise -e " $a{0} = $a{0} || scalar keys %a; print $a{0} "
n <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
f <2> sassign vKS/2 ->g
- <1> null sK/1 ->b
7 <|> or(other->8) sK/1 ->b
6 <2> helem sK/2 ->7
4 <1> rv2hv sKR/1 ->5
3 <#> gv[*a] s ->4
5 <$> const[PV "0"] s ->6
- <1> scalar sK/1 ->-
a <1> keys[t5] sK/1 ->b
9 <1> rv2hv[t4] lKRM/1 ->a
8 <#> gv[*a] s ->9
e <2> helem sKRM*/2 ->f
c <1> rv2hv sKR/1 ->d
b <#> gv[*a] s ->c
d <$> const[PV "0"] s ->e
g <;> nextstate(main 1 -e:1) v:{ ->h
m <@> print vK ->n
h <0> pushmark s ->i
l <2> helem sK/2 ->m
j <1> rv2hv sKR/1 ->k
i <#> gv[*a] s ->j
k <$> const[PV "0"] s ->l
-e syntax OK
|
| [reply] [d/l] [select] |
While it might be “inconsistent behavior,” it is also, clearly, “unpredictable code” that is dependent upon (and thus, vulnerable to) language implementation quirks. If it matters what the language is to do, “when, and in what order,” then you are obliged to say so. Otherwise, the optimizer can, and will, make sometimes-arbitrary decisions. (“Heads, or tails? If it doesn’t seem to matter, then I (the optimizer...) get to choose, and by the way, to do my job I must do so.”) And when that happens, “whose fault is it, really?” You knew ... you were warned. Code like that is curious, maybe, but it’s also intrinsically defective. It’s fun to play “Perl golf,” but don’t make your daily bread that way.
(And although that statement as-writ might sound like some kind of weighty pronouncement ... I’m really in a very pleasant mood, with good music playing and good coffee in my hand. It’s just an observation.)
| |
perl -e '$a{0} = $a{0} || scalar keys %a; print $a{0}'
Basically, accessing $a{0} on the right hand side of your assignment creates the key, so scalar keys %a equals 1.
Documentation is available: on perlmonks, on perldoc, and on cpan. You can also do a super search for autovivification.
Update: It's a bug. See below for details. | [reply] [d/l] [select] |
is it a bug or feature?
Neither. It looks like undefined behavior to me. (Not joking.)
My response to "What do you think this would print?" was "Either 0 or 1, depending on subtle evaluation order concerns that are likely to change for 1) rather arbitrary reasons of implementation details and/or 2) as a result of optimizations". Either result is acceptable. That's why you shouldn't write code like that.
Basically, accessing $a{0} on the right hand side of your assignment creates the key
Actually, that can't be a valid explanation. The right-hand side instance of $a{0} is not in a "lvalue context"; that is, it is simply being read, not (potentially) being written to. So the (implicit or imagined) right-hand side instance of $a{0} does not trigger autovification.
It is the $a{0} on the left-hand side of the assignment that triggers vivification (not necessarily autovivification). It is just an implementation detail as to whether the slot for storing the value is created before or after keys %a gets evaluated.
Since Anonymous Monk shows that the answer is different (at least for some versions of Perl) in the case of the explicit version of "the same thing",
$a{0}= $a{0} || scalar keys %a;
I suspect that this really is the result of an optimization. ||= knows that it needs to both read from and write to the item on the left-hand side. So it just grabs a can-be-written-to instance of the left-hand side up front, which means the key slot gets allocated before the (implicit) || gets executed.
In $a{0}= $a{1} || scalar keys %a;, the $a{1} must be read before the || can decide whether or not to evaluate scalar keys %a. That does not autovivify $a{1}. The $a{0} has to be vivified and it is an implementation detail as to whether this is done before or after the other things to be done. It appears that at least some implementations of Perl vivify $a{0} after the right-hand side value has been computed.
| [reply] [d/l] [select] |
$ perl -e '$a{0} = $a{0} || scalar keys %a; print $a{0}'
0
$ perl -e '$a{0} ||= scalar keys %a; print $a{0}'
1
Tested on 5.8, 5.10, and 5.12
| [reply] [d/l] |