develooper Front page | perl.perl5.porters | Postings from March 2007

Re: Differences between state variables and smart matches in 5.10 and 6

Thread Previous | Thread Next
From:
Rafael Garcia-Suarez
Date:
March 26, 2007 01:16
Subject:
Re: Differences between state variables and smart matches in 5.10 and 6
Message ID:
b77c1dce0703260116p148b1efw26dc1bf81482163e@mail.gmail.com
On 26/03/07, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:
> It was discussed on #p5p that state variables in 5.10 will always
> evaluate the expression on the RHS and discard the value in later
> calls, example:
>
> $ perl5.9.5 -E 'sub res { print "eek"; int rand 1337 } sub { state $x
> = res(); print "$x\n" }->() for 1 .. 2'
> eek392
> eek392
>
> Pugs does not do this currently doing the right thing (IMO):
>
> $ pugs -e 'my sub res { say "eek"; int rand 1337 } my sub st { state
> $x = res(); say $x } st() for 1 .. 2'
> eek
> 1141
> 1141

Yes, that's how Perl 6 specifies it. However I think that would be
much more difficult to implement in Perl 5.
Here's the opcode for Perl 5:

$ bleadperl -MO=Concise -E 'state $x = foo()'
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 40 -e:1) v:%,{ ->3
7     <2> sassign vKS/STATE,2 ->8
5        <1> entersub[t2] sKS/TARG,1 ->6
-           <1> ex-list sK ->5
3              <0> pushmark s ->4
-              <1> ex-rv2cv sK ->-
4                 <$> gv(*foo) s/EARLYCV ->5
6        <0> padsv[$x:40,41] sRM*/LVINTRO,STATE ->7

state() is implemented by a combination of flags, one on the
assignment op that indicates that this is an assignment to a state
variable, and one on the pad variable that indicates that it has been
initialized. If you want to discard the whole right side of the
assignment, effectively implementing Perl 6's "once" blocks, you'd
have to modify the optree at runtime. And that's something we can't
do, since optrees are shared between threads.

> Similarly s/// doesn't work with smart matching as it does in Perl 6:
>
> $ pugs -e 'my $str = "baab"; $str ~~ s:g/a//; say $str'
> bb
>
> $ perl5.9.5 -E 'my $str = "baaab"; $_ = $str; $str ~~ s/a//g; say $str; say $_'
> baaab
> bb
>
> $str ~~ s/a//g; means $str ~~ ($_ =~ s/a//g) in 5.10;
>
> The state issue can sort of be worked around by doing:
>
> state $x //= func();
>
> and the s/// issue by using =~ instead, but these constructs should
> mirror their v6 functionality, should they not?

The ~~ table in perlsyn doesn't mention s///, so it's an unimplemented
feature. I remember having asked Damian about this, and he found the
Perl 5 smart match good enough (there are other small differences with
Perl 6's smart match.) However, if someone wants to implement ~~s///,
patches welcome. But fast, since I want to enter a feature freeze
phase for 5.10 soon...

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About