| =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.