Perl v5.28 allows you to initialize array and hash variables that you declare with state . This is a feature a long time coming and that I’m quite happy as finally arrived.

Since v5.10 and up to v5.26 you could only initialize a state variable if it was a scalar. You could declare a hash or array variable but you couldn’t give it an initial value at the same time. You could do this:

use v5.26; sub do_it { state $previous_argument = 0; ... }

But you can’t give an array or hash initial values. You can’t assign to them at all. “Initializing” them to an empty list won’t work:

use v5.26; sub do_it { state @previous_arguments = (); # ERROR push @previous_arguments, @_; ... }

The error gives some hope that the situation will change:

Initialization of state variables in list context currently forbidden

References are one way around this because they are scalar variables. Instead of an array or hash, use an array or a hash reference.

use v5.26; sub do_it { state $previous_arguments = []; push @$previous_arguments, @_; ... }

Since you can initialize the array reference you can give it values before the actual arguments of the first call:

use v5.26; sub do_it { state $previous_arguments = [ qw(this that) ]; push @$previous_arguments, @_; ... }

With v5.28 you can skip the references and the dereferencing. This is slightly cleaner and amenable to people still grappling with the idea of references:

use v5.28; sub do_it { state @previous_arguments = qw( this that ); push @previous_arguments, @_; ... }

Fibonacci caching

In Mastering Perl I show a caching Fibonacci generator. If you intend on using many of these numbers you don’t want to recompute what you already know. You can trade a bit of memory for some speed by caching prior work. Here’s the same thing using an array variable:

use v5.28; foreach my $n ( 0 .. 100 ) { say fibonacci( $n ); } sub fibonacci { state @Cached = qw( 1 1 ); my( $n ) = @_; return $Cached[$n] if $n <= $#Cached; foreach my $i ( $#Cached + 1 .. $n ) { $Cached[$i] = $Cached[-1] + $Cached[-2]; } return $Cached[$n]; }

Here's that same subroutine prior to v5.28. It's a bit more ugly although perfectly serviceable. It uses an array reference so there are some added dereferencing arrows and an accretion of symbols to get the last index ( $#$Cached ):

use v5.26; sub fibonacci { state $Cached = [ qw( 1 1 ) ]; my( $n ) = @_; return $Cached->[$n] if $n <= $#$Cached; foreach my $i ( $#$Cached + 1 .. $n ) { $Cached->[$i] = $Cached->[-1] + $Cached->[-2]; } return $Cached->[$n]; }