I suppose it could be useful for "aggressive caching" if, you want to control access to this variable inside of the subroutine; but that's not really the point of the state declaration.
It is useful for creating subroutines that maintain a sense of state; for example you may use it to stop a subroutine at one point (state 0 -> state 1) and on the next call it, it will be able to pick up at state 1 (then maybe return when in state 2). Below is a finite state machine implemented lexically inside of a single subroutine using state, which matches on the regular expression ab(ab)*c.
use strict;
use warnings;
use feature 'state';
my $test_string = $ARGV[0] // q{ababababac};
sub transition {
my $symbol = shift;
state $current = 'start'; # initialize on first call to __SUB__
my $trans = {
start => { a => 1, b => 'start', c => 'sink' },
1 => { a => 1, b => 'start', c => 'final' },
final => { a => 'sink', b => 'sink', c => 'sink' },
};
my $next =
( $trans->{$current}->{$symbol} )
? $trans->{$current}->{$symbol}
: q{sink};
print qq{$current -> $next on "$symbol"\n};
$current = $next; # update stateful var, will be this valu
+e on next call to __SUB__
return $current;
}
my $position;
for my $s ( split //, $test_string ) {
$position = transition($s);
}
printf( qq{string "%s" is %s\n}, $test_string, ( $position eq q{final}
+ ) ? q{ACCEPTED} : q{REJECTED} );
Output (ACCEPTED):
$ perl state.pl abababac
start -> 1 on "a"
1 -> start on "b"
start -> 1 on "a"
1 -> start on "b"
start -> 1 on "a"
1 -> start on "b"
start -> 1 on "a"
1 -> final on "c"
string "abababac" is ACCEPTED
Output (REJECTED):
perl state.pl abababa
start -> 1 on "a"
1 -> start on "b"
start -> 1 on "a"
1 -> start on "b"
start -> 1 on "a"
1 -> start on "b"
start -> 1 on "a"
string "abababa" is REJECTED
The primary use case I am showing here is that, what would normally need to be global in scope can now be cleanly scoped lexically within the subroutine, transition. Can state be used for caching? Yes, but no more effectively than using a global variable. |