On Fri, Aug 19, 2016 at 11:05:07AM -0700, Will Coleda via RT wrote:
> On Sat Nov 05 09:12:36 2011, moritz wrote:
> > 16:28 < moritz> perl6: sub f($x) { return if $x == 1; state %h = a => 1;
> > say
> >                 %h.perl }; f 1; f 2;
> > 16:28 <+p6eval> niecza v11-20-gb962c2f: OUTPUT«{"a" => 1}.hash␤»
> > 16:28 <+p6eval> ..pugs b927740: OUTPUT«{("a" => 1),}␤»
> > 16:28 <+p6eval> ..rakudo 9c2880: OUTPUT«().hash␤»
> > 
> > I'm pretty sure that's a bug (and not limited to hashes, same for scalar
> > state vars).
> > 
> > I've added a test to S04-declarations/state.t
> 
> Bug still present in rakudo-moar 079da9

$ perl -E 'sub f { my $x = shift; return if $x == 1; state $h = 42; say $h; }; 
f 1; f 2;'                              
42

Works on Perl 5 :-)

I thought that the Perl 6 implementation of state had overtaken the Perl 5
implementation years ago. Interesting that a bug still remains :-)

The Perl 5 implementation (which is a hack) stores the START-ness as a flag
on the lexical, so this bug can't even happen.

It's the 'once' op at position 'f', which the first time branches to 'g'
(and hence then flows to 'h', 'i' and 'j') to call the expression on the
right of the = and then assign the value. Subsequent calls are from 'f' to
'g' to 'j', which just reads from the variable, and never executes the RHS.

Note that the 'once' op has the lexical $h as an argument, so that it can
set/read the START flag.

$ perl -MO=Concise,f,-exec -E 'sub f { my $x = shift; return if $x == 1; state 
$h = 42; say $h; }; f 1; f 2;'
main::f:
1  <;> nextstate(main 47 -e:1) v:%,2048
2  <$> gv(*_) s
3  <1> rv2av[t2] sKRM/1
4  <1> shift sK/1
5  <0> padsv[$x:47,49] sRM*/LVINTRO
6  <2> sassign vKS/2
7  <;> nextstate(main 48 -e:1) v:%,2048
8  <0> padsv[$x:47,49] s
9  <$> const(IV 1) s
a  <2> eq sK/2
b  <|> and(other->c) vK/1
c      <0> pushmark s
d      <@> return K
e  <;> nextstate(main 48 -e:1) v:%,{,2048
f  <|> once(other->g)[$h:48,49] vK/1
g      <$> const(IV 42) s
h      <0> padsv[$h:48,49] sRM*/LVINTRO,STATE
i      <2> sassign KS/2
           goto j
o  <0> padsv[$h:48,49] sRM*/STATE
j  <;> nextstate(main 49 -e:1) v:%,{,2048
k  <0> pushmark s
l  <0> padsv[$h:48,49] l
m  <@> say sK
n  <1> leavesub[1 ref] K/REFC,1
-e syntax OK

Nicholas Clark

Reply via email to