FSA::Engine - A Moose Role to convert an object into a Finite State Machine.
Create a Package which defines your FSA states and transition rules.
package PingPong; use Moose; with 'FSA::Engine'; has 'counter' => ( is => 'rw', isa => 'Int', default => 0, ); sub _build_fsa_states { return { ping => { entry_action => sub {print "ping!\n";}, }, pong => { entry_action => sub {print "pong!\n";}, }, game_over => { }, }; } sub _build_fsa_transitions { return { ping => { ... }, pong => { ... }, game_over => { ... }, # see BUILD_METHODS below for a full example }; } 1;
Create an instance of your class
use PingPong; my $game = PingPong->new({ fsa_state => 'ping' }); while ($game->fsa_state ne 'game_over') { $game->fsa_check_state; }
This Moose Role allows you to implement a simple state machine in your class by defining the transitions and the states that comprise that state machine.
All you need to do to transform your class into a FSA is to with 'FSA::Engine'.
with 'FSA::Engine'
This is not an ideal DFA implementation since it does not enforce a single possible switch from one state to another, instead it short-circuits the evaluation at the first rule to return true.
FSA::Engine uses named states and named transitions so it is easier to tell what state you are in.
Optionally, each state can have an entry and an exit action that are triggered when the state is entered and exited.
Each state may define transition rules which determine the conditions to switch to other states and these rules may optionally define actions to carry out if the rules are followed.
There are some attributes that require building methods.
sub _build_fsa_states { return { ping => { entry_action => sub {print "ping!\n";}, }, pong => { entry_action => sub {print "pong!\n";}, }, game_over => { }, }; }
The fsa_actions attribute is defined as a hash reference, where the keys are the names of each state and the value is a hash reference.
In this example the states are ping, pong and game_over. The hash reference referred to by each state has the following optional keys.
This is an anonymous subroutine that (if defined) will be called when the state is entered.
The entry_action will be called after any Transition action that may have been called leading to this state.
This is an anonymous subroutine that (if defined) will be called when the state is exited.
The exit_action is called before any Transition action called leaving this state.
sub _build_fsa_transitions { return { foo_state => { transition_one => { ... }, transition_two => { ... }, }, bar_state => { transition_three => { ... }, }, }; }
The fsa_transitions attribute is defined as a hash reference, where the keys are the names of each state and the value is a hash reference of the transitions possible from that state. A more complete example is as follows (which goes with the SYNOPSIS)
sub _build_fsa_transitions { my ($self) = @_; return { ping => { volley => FSA::Engine::Transition->new({ test => sub {$self->counter < 20;}, action => sub {$self->counter($self->counter+1);}, state => 'pong', }), end_of_game => FSA::Engine::Transition->new({ test => sub {$self->counter >= 20;}, action => sub {print "Game over\n";}, state => 'game_over', }), }, pong => { return_volley => FSA::Engine::Transition->new({ test => sub {1;}, # always goes back to ping state => 'ping', }), }, game_over => { }, }; }
The transition names ping, pong and game_over are keys to FSA::Engine::Transition objects which will define the test to carry out, an optional action to carry out if the test succeeds and the state to move to if the test succeeds.
Each test is made until one succeeds at which point the action (if any) is carried out and the FSA state is advanced to state.
When a test succeeds, all futher tests are short-circuited. Note that this action may change in future releases.
An FSA class will have the following additional methods:
$new_state = $my_fsa->fsa_check_state; $new_state = $my_fsa->fsa_check_state($input);
Check for a state change in the FSA, optionally a new input value can be provided.
If the state machine changes state, then the new state (name) is returned, otherwise it returns undef
undef
An FSA class will have the following additional attributes:
This is a required attribute.
my $game = PingPong->new({ fsa_state => 'ping', });
When used during construction the fsa_state determines the initial state of the FSA.
fsa_state
$current_state = $my_fsa->fsa_state;
At other times it returns the current state of the FSA.
You can find information at:
AnnoCPAN: Annotated CPAN documentation
http://annocpan.org/dist/FSA-Engine
CPAN Ratings
http://cpanratings.perl.org/i/FSA-Engine
RT: CPAN's request tracker
http://rt.cpan.org/NoAuth/Bugs.html?Dist=FSA-Engine
Search CPAN
http://search.cpan.org/dist/FSA-Engine
This module was influenced in part by FSA::Rules which implements an FSA using a traditional Perl OO method.
Ian C. Docherty <pause@iandocherty.com>
Thanks also to James Spurin <pause@twitchy.net> for support and advice.
Thanks to various members of the Moose mailing list for recommendations on how to name this module.
Copyright(c) 2011 Ian C. Docherty
This module is free software; you can distribute it and/or modify it under the same terms as Perl itself.
To install FSA::Engine, copy and paste the appropriate command in to your terminal.
cpanm
cpanm FSA::Engine
CPAN shell
perl -MCPAN -e shell install FSA::Engine
For more information on module installation, please visit the detailed CPAN module installation guide.