Creating Persistent Private Variables (Perl Cookbook, 2nd Edition)

## 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[18] 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.

> [18]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

Copyright © 2003 O'Reilly & Associates. All rights reserved.