Name FSA::Rules - Build simple rules-based state machines in Perl Synopsis my $fsa = FSA::Rules->new( ping => { do => sub { print "ping!\n"; my $state = shift; $state->result('pong'); $state->machine->{count}++; }, rules => [ game_over => sub { shift->machine->{count} >= 20 }, pong => sub { shift->result eq 'pong' }, ], }, pong => { do => sub { print "pong!\n" }, rules => [ ping => 1, ], # always goes back to ping }, game_over => { do => sub { print "Game Over\n" } } ); $fsa->start; $fsa->switch until $fsa->at('game_over'); Description This class implements a simple state machine pattern, allowing you to quickly build rules-based state machines in Perl. As a simple implementation of a powerful concept, it differs slightly from an ideal DFA model in that it does not enforce a single possible switch from one state to another. Rather, it short circuits the evaluation of the rules for such switches, so that the first rule to return a true value will trigger its switch and no other switch rules will be checked. (But see the `strict' attribute and parameter to `new()'.) It differs from an NFA model in that it offers no back-tracking. But in truth, you can use it to build a state machine that adheres to either model--hence the more generic FSA moniker. FSA::Rules uses named states so that it's easy to tell what state you're in and what state you want to go to. Each state may optionally define actions that are triggered upon entering the state, after entering the state, and upon exiting the state. They may also define rules for switching to other states, and these rules may specify the execution of switch-specific actions. All actions are defined in terms of anonymous subroutines that should expect an FSA::State object itself to be passed as the sole argument. FSA::Rules objects and the FSA::State objects that make them up are all implemented as empty hash references. This design allows the action subroutines to use the FSA::State object passed as the sole argument, as well as the FSA::Rules object available via its `machine()' method, to stash data for other states to access, without the possibility of interfering with the state or the state machine itself. Serialization As of version 0.24, FSA::Rules supports serialization by Storable 2.05 and later. In other words, FSA::Rules can function as a persistent state machine. However, FSA::Rules stores data outside of FSA::Rules objects, in private data structures inside the FSA::Rules module itself. Therefore, unless you want to clone your FSA::Rules object, you must let it fall out of scope after you serialize it, so that its data will be cleared from memory. Otherwise, if you freeze and thaw an FSA::Rules object in a single process without `undef'ing the original, there will be *two* copies of the object stored by FSA::Rules. So how does it work? Because the rules are defined as code references, you must use Storable 2.05 or later and set its `$Deparse' and `$Eval' variables to true values: use Storable qw(freeze thaw); local $Storable::Deparse = 1; local $Storable::Eval = 1; my $frozen = freeze($fsa); $fsa = thaw($frozen); The only caveat is that, while Storable can serialize code references, it doesn't properly reference closure variables. So if your rules code references are closures, you'll have to serialize the data that they refer to yourself. Class Interface Constructor