--- name: state signature: 'state VARLIST' since: 5.10 status: documented categories: ["Scoping"] --- ```{index} single: state; Perl built-in ``` *[Scoping](../perlfunc-by-category)* # state Declare a lexically scoped variable whose value persists across calls to its enclosing subroutine. A `state` variable has the same visibility rules as a [`my`](my) variable — it is visible only inside the block that declares it — but it is **initialised exactly once** per enclosing closure, not on every entry to the block. This is Perl's built-in way to write persistent private variables: counters, memoisation caches, one-time-computed lookup tables, anything you would otherwise hide inside a file-scoped lexical above a `sub`. ## Synopsis ```perl state $scalar state $scalar = EXPR state ($a, $b, undef, $c) state @array state %hash state TYPE $var state $var : ATTRS ``` ## What you get back `state` is a declaration, not a function. Like [`my`](my) it returns the variable(s) it declares, so it can be used in any expression position where the declared variable would appear: ```perl (state $n //= 0)++; # declare-and-use in one expression print ++(state $calls), "\n"; # count calls to this line ``` The initialiser on the right of `=` is evaluated **only the first time control flows through the declaration** in that particular closure instance. On every subsequent entry, the declaration re-exposes the already-initialised variable and the initialiser is skipped. ## Persistence scope — what "once" means "Once per enclosing closure" is the precise rule. A `state` variable lives as long as the CV (code value) that contains its declaration: - In a **named sub**, the CV is created once at compile time. The `state` variable is initialised on the first call and retains its value across every later call for the life of the process. - In an **anonymous sub / closure**, each `sub { ... }` evaluation produces a fresh CV with its own fresh `state` slot. Two closures made from the same source do **not** share state. - In a **nested block** inside a sub, the `state` still belongs to the surrounding CV — it is not re-created on each entry to the inner block. ```perl sub counter { state $n = 0; ++$n } counter(); counter(); counter(); # returns 1, 2, 3 my $make = sub { sub { state $n = 0; ++$n } }; my $a = $make->(); my $b = $make->(); $a->(); $a->(); $b->(); # $a sees 1, 2; $b sees 1 ``` ## Feature gate and availability `state` has always been feature-gated. Two ways to enable it: - `use feature 'state';` — turns on just this feature. - `use v5.10;` (or any later version bundle, including `use v5.36` and `use v5.42`) — implicit via the version feature bundle. Every modern program already has `state` available through its `use vX.Y` line. Without the feature in scope, `state` is parsed as an ordinary bareword. To reach the built-in unconditionally, write `CORE::state`. ```perl use v5.36; # 'state' feature is on by default sub hits { state $n = 0; ++$n } ``` ## List declarations and initialisers `state` supports the parenthesised list form for declaring several variables at once, with [`undef`](undef) as a placeholder: ```perl state ($x, $y, undef, $z); ``` What it does **not** yet support is **initialising a list** of `state` variables. Upstream explicitly notes this: initialisation of `state` variables in a parenthesised list is not currently possible, so the list form is useful only for declaration. Aggregates — `state @array` and `state %hash` — have historically had the same restriction on initialisers (Perl emitted an experimental warning, and in several versions a syntax error, for `state @a = (1, 2, 3)`). Build the aggregate inside the body instead: ```perl sub primes_below_100 { state @p; unless (@p) { @p = _sieve(100); # fill on first call only } return @p; } ``` The `unless (@p)` / `unless (%h)` idiom above is the portable replacement for an aggregate initialiser. ## Declaration placement and same-statement semantics Like [`my`](my), [`our`](our), and [`local`](local), a `state` declaration can appear anywhere an expression is allowed (except inside string interpolation). The new binding takes effect for **subsequent statements**, not for other mentions of the same variable in the same statement: ```perl package main; use feature 'state'; our $x = 2; foo($x, state $x = $x + 1, $x); # foo() receives (2, 3, 2) foo($x, $main::x); # foo() receives (3, 2) ``` The first `$x` and the trailing `$x` in the same call still refer to `our $x`; only the next statement sees the `state $x`. ## Examples A hit counter — the canonical one-liner: ```perl sub hits { state $n = 0; ++$n } hits(); hits(); hits(); # returns 1, 2, 3 ``` Memoisation of an expensive pure function: ```perl sub fib { my ($n) = @_; state %cache; return $cache{$n} //= $n < 2 ? $n : fib($n-1) + fib($n-2); } ``` Lazy one-time setup of a read-only table: ```perl sub months { state @m = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); return @m; } ``` Here the initialiser is a simple list, which works because the RHS of `state @m = ...` is constant-folded to a list literal and current Perl permits this form; the more general case of a computed list still wants the `unless (@m) { ... }` pattern above for portability. Per-closure state (fresh slot per `sub { ... }` evaluation): ```perl sub make_counter { return sub { state $n = 0; ++$n }; } my $a = make_counter(); my $b = make_counter(); $a->(); $a->(); # 1, 2 $b->(); # 1 — independent of $a ``` Declare-and-use in a single expression: ```perl while (my $line = <$fh>) { warn "first line was: $line" if (state $first //= $line) eq $line; } ``` ## Edge cases - **Aggregate initialisers.** `state @a = (1, 2, 3)` and `state %h = (k => 1)` have a long history of being restricted or experimental. When in doubt, declare the aggregate and fill it under `unless (@a) { ... }` on the first call. Scalar initialisers (`state $x = EXPR`) have always been fine. - **Same-statement reuse.** A fresh `state` declaration does **not** apply to other mentions of the same name within the same statement; those still resolve to whatever was in scope before the declaration. See the `foo($x, state $x = $x + 1, $x)` example above. - **Shadowing warning.** Redeclaring the same name in the same scope — `state $n; state $n;` — shadows the first. Under `use warnings` this emits a warning in the `shadow` category. Almost always a bug. - **Anonymous-sub multiplicity.** Every evaluation of `sub { ... }` produces a new CV with its own `state` slot. If you build many closures from the same source, each has its own independent `state` — that is a feature, but it surprises people expecting file-scoped persistence. - **Threads and forks.** `state` lives in the CV, which is cloned on `fork` (copy-on-write in the OS sense — each process continues with its own copy) and on `threads->create` (deep-cloned). Two processes or threads do not share a `state` counter. - **`local` does not apply.** `state` variables are lexicals, not package variables, so [`local`](local) cannot save and restore them. Wrap the whole sub in its own scope or use a different mechanism if you need dynamic scoping. - **Access via `CORE::state`.** When writing code that must parse even without the feature enabled, prefix the keyword: `CORE::state $n = 0;`. - **Destruction.** `state` variables live as long as the CV. For a named sub in the main program that means "until global destruction." Do not put a file-handle or a large buffer in a `state` variable expecting it to be freed at sub exit — it will not be. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`my`](my) — ordinary lexical; reinitialised on every block entry, the natural contrast to `state` - [`our`](our) — lexical alias for a package variable; use when callers need to see or `local`-ise the value - [`local`](local) — dynamic scoping for package variables; orthogonal to `state` and cannot be applied to it - [`sub`](sub) — `state` lives inside a CV; understanding how named vs anonymous subs differ explains per-closure state - [`use`](use) — `use v5.10` and later enable the `state` feature as part of the version bundle - [`undef`](undef) — legal placeholder inside `state (...)` list declarations