-
-
Save dha/8009c28d7bf2d1ca8875 to your computer and use it in GitHub Desktop.
=begin pod | |
C<state> declares lexically scoped variables, just like C<my>. However, | |
initialization happens exactly once the first time the initialization | |
is encountered in the normal flow of execution. Thus, state variables | |
will retain their value across multiple executions of the enclosing | |
block or routine. | |
Therefore, the subroutine | |
=begin code | |
sub a { | |
state @x = 1, 1; | |
@x.push(1, 1) | |
} | |
=end code | |
will continue to append each time it is called. So, | |
=begin code | |
say a; | |
say "next"; | |
say a; | |
say "next"; | |
say a; | |
=end code | |
will output | |
=begin code | |
[1 1 1 1] | |
next | |
[1 1 1 1 1 1] | |
next | |
[1 1 1 1 1 1 1 1] | |
=end code | |
Also, just like C<my>, declaring multiple variables must be placed in | |
parentheses and for declaring a single variable, parentheses may be | |
omitted. Within a parenthesized list, C<$> can be used as a dummy | |
placeholder. | |
In fact, C<$> can be used as an anonymous state variable without an explicit C<state> declaration. | |
=begin code | |
perl6 -e 'sub foo() { say ++$ }; foo() for ^3' | |
=end code | |
produces | |
=begin code | |
1 | |
2 | |
3 | |
=end code | |
Furthermore, state variables are not required to exist in | |
subroutines. You could, for example, use C<$> in a one-liner to | |
number the lines in a file. | |
=begin code | |
perl6 -ne 'say ++$ ~ " $_"' example.txt | |
=end code | |
Finally, if you were to use multiple anonymous state variables, they would | |
fuction independently. | |
=begin code | |
perl6 -e '{ say ++$; say ++$ } for ^5' | |
=end code | |
would produce | |
=begin code | |
1 | |
1 | |
2 | |
2 | |
3 | |
3 | |
4 | |
4 | |
5 | |
5 | |
=end pod |
state variables will retain their value across multiple executions of the enclosing block or routine.
I'm not sure of the official terminological distinction between blocks and closures, but let's say a "source block" is a chunk of source code and its enclosing pair of braces and a "run-time block" is the executabble equivalent at run-time. Then one needs to be aware that, while there's usually a 1-to-1 correspondence, that's not always the case -- there can be multiple run-time copies of the same source block in some scenarios. Examples:
sub foo { ++$ }; say foo for ^2
1
2
say { ++$ }() foo for ^2
1
1
This is called "closure cloning" in http://design.perl6.org/S04.html. (Note, this is not the same as other forms of cloning such as object cloning.) Probably gets especially interesting in a multi-threaded context.
Within a parenthesized list, C<$> can be used as a dummy placeholder.
I don't think a dummy placeholder is a state variable. I don't think that bit belongs on this page.
In fact, C<$> can be used as an anonymous state variable in subroutines without a C declaration.
Not just in subroutines but in any code where a state variable is valid:
perl6 -e 'say ++$ for ^2'
I think this deserves its own subhead ("Anonymous state variables") or somesuch.
Updated gist to cover the issues noted.
Excellent! The only thing I would change would be the first example using different numbers for the initialization versus the subsequent pushes. dha++
Excellent!
The only thing I miss is an explanation of the scoping rules of state, e.g. when used in a block, or with recursive calls. As I'm unsure myself how this works exactly, some research / community support may be necessary to get this together.