Who has the best state
implementation? (For some arbitrary definition of "best".) Let's see:
$ cat state.pl sub foo { state $bar = "Pie"; say $bar; $bar = "Good"; } foo(); foo();
$ ./parrot languages/perl6/perl6.pbc state.pl scope declarator 'state' not implemented at line 2, near "= \"Pie\";\n " current instr.: 'parrot;PGE::Util;die' pc 120 (runtime/parrot/library/PGE/Util.pir:82) called from Sub 'parrot;Perl6;Grammar;Actions;_block1900' pc 107647 (src/gen_actions.pir:5109) called from Sub 'parrot;Perl6;Grammar;Actions;_block1890' pc 107410 (src/gen_actions.pir:5015) called from Sub 'parrot;Perl6;Grammar;Actions;_block1864' pc 107316 (src/gen_actions.pir:4975) called from Sub 'parrot;Perl6;Grammar;Actions;scope_declarator' pc 105807 (src/gen_actions.pir:4402) called from Sub 'parrot;Perl6::Grammar;scope_declarator' pc 73809 (src/gen_grammar.pir:22436) called from Sub 'parrot;Perl6::Grammar;noun' pc 66663 (src/gen_grammar.pir:19982) called from Sub 'parrot;Perl6::Grammar;term' pc 62462 (src/gen_grammar.pir:18460) called from Sub 'parrot;PGE::OPTable;parse' pc 1998 (compilers/pge/PGE/OPTable.pir:532) called from Sub 'parrot;Perl6::Grammar;statement' pc 18468 (src/gen_grammar.pir:3117) called from Sub 'parrot;Perl6::Grammar;statementlist' pc 15720 (src/gen_grammar.pir:2170) called from Sub 'parrot;Perl6::Grammar;statement_block' pc 13578 (src/gen_grammar.pir:1384) called from Sub 'parrot;Perl6::Grammar;block' pc 14687 (src/gen_grammar.pir:1795) called from Sub 'parrot;Perl6::Grammar;routine_def' pc 48620 (src/gen_grammar.pir:13549) called from Sub 'parrot;Perl6::Grammar;routine_declarator' pc 47075 (src/gen_grammar.pir:13013) called from Sub 'parrot;Perl6::Grammar;noun' pc 66887 (src/gen_grammar.pir:20052) called from Sub 'parrot;Perl6::Grammar;term' pc 62462 (src/gen_grammar.pir:18460) called from Sub 'parrot;PGE::OPTable;parse' pc 1998 (compilers/pge/PGE/OPTable.pir:532) called from Sub 'parrot;Perl6::Grammar;statement' pc 18468 (src/gen_grammar.pir:3117) called from Sub 'parrot;Perl6::Grammar;statementlist' pc 15720 (src/gen_grammar.pir:2170) called from Sub 'parrot;Perl6::Grammar;statement_block' pc 13578 (src/gen_grammar.pir:1384) called from Sub 'parrot;Perl6::Grammar;TOP' pc 10420 (src/gen_grammar.pir:204) called from Sub 'parrot;PCT::HLLCompiler;parse' pc 564 (src/PCT/HLLCompiler.pir:348) called from Sub 'parrot;PCT::HLLCompiler;compile' pc 440 (src/PCT/HLLCompiler.pir:291) called from Sub 'parrot;PCT::HLLCompiler;eval' pc 755 (src/PCT/HLLCompiler.pir:450) called from Sub 'parrot;PCT::HLLCompiler;evalfiles' pc 1067 (src/PCT/HLLCompiler.pir:587) called from Sub 'parrot;PCT::HLLCompiler;command_line' pc 1246 (src/PCT/HLLCompiler.pir:676) called from Sub 'parrot;Perl6::Compiler;main' pc 8860 (perl6.pir:183)
$ ./pugs state.pl Pie Pie
$ /usr/local/perl-5.10.0/bin/perl -Mfeature=:5.10 state.pl Pie Good
Yes, strange as it may seem, Perl 5 has the most complete implementation of Perl 6's state
ââ¬Â . Only Perl 5 performs an initialisation via =
once. I blame Rafael, Dave and me.
ââ¬Â At least this week. For some value of this week. Until someone reads this Perl blog and gets hacking.
It was written back in July of 2005 before pugs had OO.# Demo of the state() variable declaration.
# This is also a neat way of doing OO without actually having OO available.
#
# Please remember to update t/examples/examples.t and rename
# examples/output/cashiers if you rename/move this file.
use v6-alpha;
sub gen_cashier () {
# This variable corresponds to a class variable.
# It is shared across all "instances" of gen_cashier().
state $cash_in_store = 0;
# One could add my() variables here, which correspond to instance variables.
# These would not be shared.
# Finally, we return a hashref which maps method names to code.
return {
add => { $cash_in_store += $^amount },
del => { $cash_in_store -= $^amount },
bal => { $cash_in_store },
};
}
my $drawer;
$drawer[$_] = gen_cashier() for 1..3;
$drawer[1]<add>( 59 );
$drawer[2]<del>( 17 );
say $drawer[3]<bal>(); # This should say "42"
Re:Odd - Pug's state worked correctly back in 2005
nicholas on 2008-04-29T14:02:03
I don't think that it did. Certainly, that example is not a good enough test, because it makes all three calls to
gen_cashier
before it uses any of the closures, so it makes no difference how many times that assignment of0
is performed. If I re-write it like this
use v6-alpha;
sub gen_cashier () {
# This variable corresponds to a class variable.
# It is shared across all "instances" of gen_cashier().
state $cash_in_store = 0;
# One could add my() variables here, which correspond to instance variables.
# These would not be shared.
# Finally, we return a hashref which maps method names to code.
return {
add => { $cash_in_store += $^amount },
del => { $cash_in_store -= $^amount },
bal => { $cash_in_store },
};
}
gen_cashier()<add>( 59 );
gen_cashier()<del>( 17 );
say gen_cashier()<bal>(); # This should say "42"
then I get the wrong answer:
$./pugs examples/cashiers.pl
0If I remove the assignment of
0
, and rely onundef
becoming0
:
sub gen_cashier () {
# This variable corresponds to a class variable.
# It is shared across all "instances" of gen_cashier().
state $cash_in_store;
# One could add my() variables here, which correspond to instance variables.
# These would not be shared.
# Finally, we return a hashref which maps method names to code.
return {
add => { $cash_in_store += $^amount },
del => { $cash_in_store -= $^amount },
bal => { $cash_in_store },
};
}
gen_cashier()<add>( 59 );
gen_cashier()<del>( 17 );
say gen_cashier()<bal>(); # This should say "42"
then I get back to the right answer:
./pugs -w examples/cashiers.pl
42
state
is doing something though here - a single variable is being shared between all 3 closures. To get the same effect withmy
I have to hoistmy $cash_in_store
outside ofsub gen_cashier
In conclusion, I don't think that
state
in Pugs has regressed - it never worked quite as well the example implied.