JavaScript EditorFreeware JavaScript Editor     Perl Tutorials 



Main Page Previous Section Next Section

Recipe 10.3 Creating Persistent Private Variables

10.3.1 Problem

You want a variable to retain its value between calls to a subroutine but not be visible outside that routine. For instance, you'd like your function to keep track of how many times it was called.

10.3.2 Solution

Wrap the function in another block, then declare my variables in that block's scope rather than in the function's:

{
    my $variable;
    sub mysub {
        # ... accessing $variable
    }
}

If the variables require initialization, make that block an INIT so the variable is guaranteed to be set before the main program starts running:

INIT {
    my $variable = 1;                       # initial value
    sub othersub {                          
      # ... accessing $variable
    }
}

10.3.3 Discussion

Unlike local[2] 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. In this code, mysub uses $variable, so Perl doesn't reclaim the variable when the block around the definition of mysub ends.

[2] Technically speaking, auto variables.

Here's how to write a counter:

{
    my $counter;
    sub next_counter { return ++$counter }
}

Each time next_counter is called, it increments and returns the $counter variable. The first time next_counter is called, $counter is undefined, so it behaves as though it were 0 for the ++. The variable is not part of next_counter's scope, but rather part of the block surrounding it. No code from outside can change $counter except by calling next_counter.

Generally, you should use an INIT for the extra scope. Otherwise, you could call the function before its variables were initialized.

INIT {
    my $counter = 42;
    sub next_counter { return ++$counter }
    sub prev_counter { return --$counter }
}

This technique creates the Perl equivalent of C's static variables. Actually, it's a little better: rather than being limited to just one function, both functions share their private variable.

10.3.4 See Also

The sections on "Closures" in Chapter 8 of Programming Perl and on "Avante-Garde Compiler, Retro Interpreter" in Chapter 18 of Programming Perl; the section on "Private Variables via my( )" in perlsub(1); the section on "Package Constructors and Destructors" in perlmod(1); Recipe 11.4

    Main Page Previous Section Next Section
    


    JavaScript EditorJavaScript Verifier     Perl Tutorials


    ©