Finite state machine: Difference between revisions
Content added Content deleted
(Rescued zkl entry which had become embedded in REXX entry.) |
(add →{{header|Perl 6}}) |
||
Line 932: | Line 932: | ||
</pre> |
</pre> |
||
=={{header|Perl 6}}== |
|||
<lang perl6>#===== The state machine =====# |
|||
class StateMachine { |
|||
class State {...} |
|||
class Transition {...} |
|||
has State %!state; |
|||
has &.choose-transition is rw; |
|||
method add-state(Str $id, &action) |
|||
{ |
|||
%!state{$id} = State.new(:$id, :&action); |
|||
} |
|||
multi method add-transition(Str $from, Str $to) |
|||
{ |
|||
%!state{$from}.implicit-next = %!state{$to}; |
|||
} |
|||
multi method add-transition(Str $from, $id, Str $to) |
|||
{ |
|||
%!state{$from}.explicit-next.push: Transition.new(:$id, to => %!state{$to}); |
|||
} |
|||
method run(Str $initial-state) |
|||
{ |
|||
my $state = %!state{$initial-state}; |
|||
loop { |
|||
$state.action.(); |
|||
if $state.implicit-next -> $_ { $state = $_; } |
|||
elsif $state.explicit-next -> $_ { $state = &.choose-transition.(|$_).to; } |
|||
else { last; } |
|||
} |
|||
} |
|||
class Transition { |
|||
has $.id; |
|||
has State $.to; |
|||
} |
|||
class State { |
|||
has $.id; |
|||
has &.action; |
|||
has State $.implicit-next is rw; |
|||
has Transition @.explicit-next; |
|||
} |
|||
} |
|||
#===== Usage example: Console-based vending machine =====# |
|||
my StateMachine $machine .= new; |
|||
$machine.choose-transition = sub (*@transitions) { |
|||
say "[{.key + 1}] {.value.id}" for @transitions.pairs; |
|||
loop { |
|||
my $n = val get; |
|||
return @transitions[$n - 1] if $n ~~ Int && $n ~~ 1..@transitions; |
|||
say "Invalid input; try again."; |
|||
} |
|||
} |
|||
$machine.add-state("ready", { say "Please deposit coins."; }); |
|||
$machine.add-state("waiting", { say "Please select a product."; }); |
|||
$machine.add-state("dispense", { sleep 2; say "Please remove product from tray."; }); |
|||
$machine.add-state("refunding", { sleep 1; say "Refunding money..."; }); |
|||
$machine.add-state("exit", { say "Shutting down..."; }); |
|||
$machine.add-transition("ready", "quit", "exit"); |
|||
$machine.add-transition("ready", "deposit", "waiting"); |
|||
$machine.add-transition("waiting", "select", "dispense"); |
|||
$machine.add-transition("waiting", "refund", "refunding"); |
|||
$machine.add-transition("dispense", "remove", "ready"); |
|||
$machine.add-transition("refunding", "ready"); |
|||
$machine.run("ready");</lang> |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |