Softpanorama

May the source be with you, but remember the KISS principle ;-)
Contents Bulletin Scripting in shell and Perl Network troubleshooting History Humor

Perl state variables

Perl state variable are replica of PL/1 static variables. For some reason Perl language designer decide to avoid including the word "static" in Perl lexicon. 

State variable are available only since Perl 5.10 and require explicit use "use v.5.10" (or later version ) statement to be activated. That means that to enable them, you need to declare that you're using a version of Perl that's at least v5.10, for example

use v.5.10

Syntax rules

state VARLIST 

  • state TYPE VARLIST
  • state VARLIST : ATTRS
  • state TYPE VARLIST : ATTRS

    state declares a lexically scoped variable, just like my. However, those variables will never be reinitialized, contrary to lexical variables that are reinitialized each time their enclosing block is entered. See Persistent Private Variables in perlsub for details.

    If more than one variable is listed, the list must be placed in parentheses. With a parenthesized list, undef can be used as a dummy placeholder. However, since initialization of state variables in list context is currently not possible this would serve no purpose.

    state variables are enabled only when the use feature "state" pragma is in effect, unless the keyword is written as CORE::state . See also feature. Alternately, include a use v5.10 or later to the current scope.

    Unlike other variable declarations, initialization of state variables is restricted to simple scalar variables only.

    One time initialization of state variables

    Since version 5.10 of Perl  you can simply use the state feature instead of closures. The main point with state variables is that you don't have to use a BEGIN (or UNITCHECK ) block to make sure that the initialization happens before the function is called and only once.

    For example:

    use v5.14; 
    sub incr_x { 
       state $x = 10;  # initialization is performed only on the first invocation
       return $x++;
    }
    

    That function will now behave just like the previous one, returning first 10, then 11, then 12, and so on.

    Here's an example when it used to keep a priva counter  if each item:

    sub seen_count { 
    state %count; 
    my $item = shift(); 
       return ++$count{$item}; 
    } 
    
    

    You can still use arrays and hashes as state variables, but you can't magically initialize them the way you can with scalars. This isn't actually the limitation it might appear to be, because you can always store a reference to the type you want, and that is a scalar. For example, instead of: # can't use state %hash = (....) my %hash = ( READY => 1, WILLING => 1, ABLE => 1, ); as a state variable, you would use: state $hashref = { READY => 1, WILLING => 1, ABLE => 1, };

    Persistent variables via state()

    Beginning with Perl 5.10.0, you can declare variables with the state keyword in place of my. For that to work, though, you must have enabled that feature beforehand, either by using the feature pragma, or by using -E on one-liners (see feature). Beginning with Perl 5.16, the CORE::state form does not require the feature pragma.

    The state keyword creates a lexical variable (following the same scoping rules as my) that persists from one subroutine call to the next. If a state variable resides inside an anonymous subroutine, then each copy of the subroutine has its own copy of the state variable. However, the value of the state variable will still persist between calls to the same copy of the anonymous subroutine. (Don't forget that sub { ... } creates a new subroutine each time it is executed.)

    For example, the following code maintains a private counter, incremented each time the gimme_another() function is called:

    1. use feature 'state';
    2. sub gimme_another { state $x; return ++$x }

    And this example uses anonymous subroutines to create separate counters:

    1. use feature 'state';
    2. sub create_counter {
    3. return sub { state $x; return ++$x }
    4. }

    Also, since $x is lexical, it can't be reached or modified by any Perl code outside.

    When combined with variable declaration, simple scalar assignment to state variables (as in state $x = 42 ) is executed only the first time. When such statements are evaluated subsequent times, the assignment is ignored. The behavior of this sort of assignment to non-scalar variables is undefined.

    Persistent variables with closures

    Just because a lexical variable is lexically (also called statically) scoped to its enclosing block, eval, or do FILE, this doesn't mean that within a function it works like a C static. It normally works more like a C auto, but with implicit garbage collection.

    Unlike local variables in C or C++, Perl's lexical variables don't necessarily get recycled just because their scope has exited. If something more permanent is still aware of the lexical, it will stick around. So long as something else references a lexical, that lexical won't be freed--which is as it should be. You wouldn't want memory being free until you were done using it, or kept around once you were done. Automatic garbage collection takes care of this for you.

    This means that you can pass back or save away references to lexical variables, whereas to return a pointer to a C auto is a grave error. It also gives us a way to simulate C's function statics. Here's a mechanism for giving a function private variables with both lexical scoping and a static lifetime. If you do want to create something like C's static variables, just enclose the whole function in an extra block, and put the static variable outside the function but in the block.

    1. {
    2. my $secret_val = 0;
    3. sub gimme_another {
    4. return ++$secret_val;
    5. }
    6. }
    7. # $secret_val now becomes unreachable by the outside
    8. # world, but retains its value between calls to gimme_another

    If this function is being sourced in from a separate file via require or use, then this is probably just fine. If it's all in the main program, you'll need to arrange for the my to be executed early, either by putting the whole block above your main program, or more likely, placing merely a BEGIN code block around it to make sure it gets executed before your program starts to run:

    1. BEGIN {
    2. my $secret_val = 0;
    3. sub gimme_another {
    4. return ++$secret_val;
    5. }
    6. }

    See BEGIN, UNITCHECK, CHECK, INIT and END in perlmod about the special triggered code blocks, BEGIN , UNITCHECK , CHECK , INIT and END .

    If declared at the outermost scope (the file scope), then lexicals work somewhat like C's file statics. They are available to all functions in that same file declared below them, but are inaccessible from outside that file. This strategy is sometimes used in modules to create private variables that the whole module can see.