Finite state machine: Difference between revisions

Include the state in the prompt
(Include the state in the prompt)
 
(21 intermediate revisions by 13 users not shown)
Line 32:
*[https://www.youtube.com/watch?v=vhiiia1_hC4 Computers Without Memory (Finite State Automata)], A Computerphile Video.
<br/><br/>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">V states = [‘ready’ =
(‘Machine ready: (d)eposit, or (q)uit?’,
[String(‘d’), ‘q’]),
‘waiting’ =
(‘Machine waiting: (s)elect, or (r)efund?’,
[String(‘s’), ‘r’]),
‘dispense’ =
(‘Machine dispensing: please (r)emove product’,
[String(‘r’)]),
‘refunding’ =
(‘Refunding money’,
[String]())
]
V transitions = [‘ready’ =
[String(‘d’) = ‘waiting’,
String(‘q’) = ‘exit’],
‘waiting’ =
[String(‘s’) = ‘dispense’,
String(‘r’) = ‘refunding’],
‘dispense’ =
[String(‘r’) = ‘ready’],
‘refunding’ =
[‘’ = ‘ready’]]
 
F Acceptor(prompt, valids)
I valids.empty
print(prompt)
R ‘’
E
L
V resp = input(prompt)[0].lowercase()
I resp C valids
R String(resp)
 
F finite_state_machine(initial_state, exit_state)
V next_state = initial_state
V current_state = :states[next_state]
L
V response = Acceptor(current_state[0], current_state[1])
I response == exit_state
L.break
next_state = :transitions[next_state][response]
current_state = :states[next_state]
 
finite_state_machine(‘ready’, ‘q’)</syntaxhighlight>
 
{{out}}
<pre>
Machine ready: (d)eposit, or (q)uit?d
Machine waiting: (s)elect, or (r)efund?s
Machine dispensing: please (r)emove productr
Machine ready: (d)eposit, or (q)uit?d
Machine waiting: (s)elect, or (r)efund?r
Refunding money
Machine ready: (d)eposit, or (q)uit?q
</pre>
 
=={{header|ALGOL 68}}==
<syntaxhighlight lang="algol68">
BEGIN # finite state machine #
 
# mode representing a state in the FSM #
MODE FSMSTATE = STRUCT( INT state # code for the state #
, PROC INT next state # routine to change state #
);
# executes the FSM defined by states, starting from the initial state #
# and terminating when the exit state is reached #
PROC run fsm = ( []FSMSTATE states, INT initial state, exit state )VOID:
BEGIN
INT state := initial state;
WHILE state /= exit state DO
BOOL found := FALSE;
FOR s pos FROM LWB states TO UPB states WHILE NOT found DO
IF found := state OF states[ s pos ] = state THEN
state := next state OF states[ s pos ]
FI
OD;
IF NOT found THEN
# in an invalid state - restart #
print( ( "(resetting)", newline ) );
state := initial state
FI
OD
END # run fsm # ;
 
BEGIN # test FSM #
# possible states #
INT exit = 0, ready = 1, waiting = 2, dispense = 3, refunding = 4;
# prompts the user for a single character code and returns it #
# the user is re-prompted until they enter one of the characters in #
# answers #
PROC get code = ( STRING prompt, answers )CHAR:
BEGIN
CHAR response;
WHILE print( ( prompt, ": " ) );
STRING answer;
read( ( answer, newline ) );
response := IF answer = "" THEN REPR 0 ELSE answer[ LWB answer ] FI;
IF response >= "a" AND response <= "z" THEN
# convert lowercase response to upper #
response := REPR ( ABS response + ( ABS "A" - ABS "a" ) )
FI;
NOT char in string( response, NIL, answers )
DO SKIP OD;
response
END # get code # ;
 
run fsm( ( ( ready
, INT: IF "Q" = get code( "Ready : Enter D to deposit, Q to Quit", "DQ" )
THEN exit
ELSE waiting
FI
)
, ( waiting
, INT: IF "S" = get code( "Waiting : Enter S to Select, R to Refund", "SR" )
THEN dispense
ELSE refunding
FI
)
, ( dispense
, INT: BEGIN get code( "Dispensing: Remove your product and Enter R", "R" );
ready
END
)
, ( refunding
, INT: BEGIN print( ( "Refunding", newline ) ); ready END
)
)
, ready
, exit
)
 
END
 
END
</syntaxhighlight>
{{out}}
<pre>
Ready : Enter D to deposit, Q to Quit: d
Waiting : Enter S to Select, R to Refund: s
Dispensing: Remove your product and Enter R: r
Ready : Enter D to deposit, Q to Quit: d
Waiting : Enter S to Select, R to Refund: r
Refunding
Ready : Enter D to deposit, Q to Quit: q
</pre>
 
=={{header|BASIC}}==
==={{header|Commodore BASIC}}===
<syntaxhighlight lang="basic">
10 REM FINITE STATE MACHINE
20 LET MS=1: REM MACHINE STATE
30 REM 1=READY, 2=WAITING, 3=DISPENSE, 4=REFUND, 5=QUIT
40 :
50 REM MAIN LOOP
60 ON MS GOSUB 1000,2000,3000,4000,5000
70 GOTO 50
80:
1000 REM READY
1010 PRINT "MACHINE IS READY"
1020 PRINT "PRESS D-ISPENSE OR Q-UIT"
1030 INPUT KP$
1040 IF KP$ = "D" THEN MS=2: GOTO 1070
1050 IF KP$ = "Q" THEN MS=5: GOTO 1070
1060 GOTO 1030
1070 RETURN
1080 :
2000 REM WAITING
2010 PRINT "MACHINE IS WAITING"
2020 PRINT "PRESS S-ELECT OR R-EFUND"
2030 INPUT KP$
2040 IF KP$ = "S" THEN MS=3: GOTO 2070
2050 IF KP$ = "R" THEN MS=4: GOTO 2070
2060 GOTO 2030
2070 RETURN
2080 :
3000 REM DISPENSE
3010 PRINT "MACHINE DISPENSE"
3020 PRINT "PRESS C-OLLECTED PRODUCT."
3030 INPUT KP$
3040 IF KP$ = "C" THEN MS=1: GOTO 3060
3050 GOTO 3030
3060 RETURN
3070 :
4000 REM REFUND
4010 PRINT "MACHINE IS REFUND"
4020 PRINT "PRESS C-OLLECTED REFUND."
4030 INPUT KP$
4040 IF KP$ = "C" THEN MS=1: GOTO 4060
4050 GOTO 430
4060 RETURN
4070 :
5000 REM QUIT
5010 PRINT "MACHINE IS SHUTDOWN"
5020 END
</syntaxhighlight>
==={{header|Sinclair ZX81 BASIC}}===
Works with 1k of RAM.
Line 45 ⟶ 244:
Note that the program uses no variables and makes no use of the return stack: all the state is expressed in the (so to speak) state.
 
<langsyntaxhighlight lang="basic"> 10 PRINT "PRESS D(EPOSIT) OR Q(UIT)"
20 IF INKEY$="D" THEN GOTO 50
30 IF INKEY$="Q" THEN STOP
Line 59 ⟶ 258:
130 GOTO 120
140 PRINT "REFUNDED"
150 GOTO 10</langsyntaxhighlight>
{{out}}
It will be seen that the user has pressed, in order, <tt>D</tt>, <tt>R</tt>, <tt>D</tt>, <tt>S</tt>, <tt>R</tt>, and <tt>Q</tt>.
Line 73 ⟶ 272:
=={{header|C}}==
Here is a manually-constructed table-driven finite state machine that is fairly general and could be adapted to different applications.
<syntaxhighlight lang="c">
<lang C>
#include <stdio.h>
#include <ctype.h>
Line 125 ⟶ 324:
return 0;
}
</syntaxhighlight>
</lang>
Machine simulation :
<pre>
Line 143 ⟶ 342:
 
=={{header|C++}}==
<syntaxhighlight lang="c">
<lang C>
#include <map>
Line 308 ⟶ 507:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 334 ⟶ 533:
=={{header|D}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="d">import std.conv;
import std.range;
import std.stdio;
Line 398 ⟶ 597:
void main() {
fsm();
}</langsyntaxhighlight>
 
=={{header|Delphi}}==
{{Trans|Go}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program Finite_state_machine;
 
Line 487 ⟶ 686:
begin
fsm;
end.</langsyntaxhighlight>
 
 
=={{header|FreeBASIC}}==
{{trans|Phix}}
<syntaxhighlight lang="freebasic">Enum states
READY
WAITING
DISPENSE
REFUND
QUIT
End Enum '-- (or just use strings if you prefer)
 
Dim As states state = READY
Dim As String KBD = " "
Do
Print KBD
Select Case state
Case READY
Print "Machine is READY. (D)eposit or (Q)uit : ";
Do
Do: KBD = Ucase(Inkey): Loop While KBD = ""
If KBD = "D" Then state = WAITING : Exit Do
If KBD = "Q" Then state = QUIT : Exit Do
Loop
Case WAITING
Print "(S)elect product or choose to (R)efund : ";
Do
Do: KBD = Ucase(Inkey): Loop While KBD = ""
If KBD = "S" Then state = DISPENSE : Exit Do
If KBD = "R" Then state = REFUND : Exit Do
Loop
Case DISPENSE
Print "Dispensing product... ";
Print "Please (C)ollect product. : ";
Do
Do: KBD = Ucase(Inkey): Loop While KBD = ""
If KBD = "C" Then state = READY : Exit Do
Loop
Case REFUND
Print "Please collect refund."
state = READY
KBD = " "
Case QUIT
Print !"Thank you, shuttingwn now.\n"
Exit Do
End Select
Loop
Sleep</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de Phix.
</pre>
 
=={{header|Go}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 590 ⟶ 845:
func main() {
fsm()
}</langsyntaxhighlight>
 
{{out}}
Line 614 ⟶ 869:
=={{header|Groovy}}==
{{trans|Java}}
<langsyntaxhighlight lang="groovy">class FiniteStateMachine {
private enum State {
Ready(true, "Deposit", "Quit"),
Line 662 ⟶ 917:
}
}
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import System.Exit
import Data.Maybe
import Control.Monad
Line 736 ⟶ 991:
, Implicit "Refunding" "Ready" ]
finishStates = ["Exit"]
</syntaxhighlight>
</lang>
 
=={{header|J}}==
 
This seems to be what the current draft task asks for:
 
<syntaxhighlight lang="text">NB. FSM builder:
explicit=: {{
states=: ~. states,x;y
transitions=: ~. transitions,<m
FSM=: y S (<x S, m T)} (states ,&# transitions){.!._ FSM
EMPTY
}}
implicit=: ''explicit
start=: {{ '' implicit y [current=: 0 [transitions=: states=: <,FSM=: EMPTY }}
 
NB. FSM utilities
S=: state=: {{ states i.<m }}
T=: transition=: {{transitions i.<m }}
N=: next=: {{
try. 1: current=: ([ {&states) current next y catch. 0 end.
:
(<x, y transition) { FSM
}}
Snm=: statename=: {{ ;:inv m{states }}
Tnm=: transitionname=: {{ ;:inv m{transitions }}
implicits=: {{ r=.'' while. next '' do. r=.r, current end. }}</syntaxhighlight>
 
With the above implementation, the task example would look like:
 
<syntaxhighlight lang="j">NB. task example FSM:
start 'ready'
'ready' 'deposit'explicit 'waiting'
'ready' 'quit'explicit 'exit'
'waiting' 'select'explicit 'dispense'
'waiting' 'refund'explicit 'refunding'
'dispense' 'remove'explicit 'ready'
'refunding' implicit 'ready'
 
example=: {{
current=: 0
machine 'deposit'
machine 'select'
machine 'remove'
machine 'deposit'
machine 'refund'
machine 'quit'
echo 'final state: ',current statename
}}
 
machine=: {{
echo 'state: ',current statename
echo 'transition: ',y
next y
i=. implicits ''
if. #i do.
echo 'implicit transition to: ',i statename
end.
}}</syntaxhighlight>
 
More advanced examples might put the FSM in a locale (allowing for multiple, independent FSMs), add callbacks and/or parameterization on transitions, or maybe include hardware specific code.
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.util.*;
 
public class FiniteStateMachine {
Line 790 ⟶ 1,105:
}
}
}</langsyntaxhighlight>
<pre>[Deposit, Quit]
> Deposit
Line 809 ⟶ 1,124:
=={{header|JavaScript}}==
===On browser using blocking window methods===
<langsyntaxhighlight JavaScriptlang="javascript">//States
var states = [{
'name': 'Ready',
Line 877 ⟶ 1,192:
}
}
</syntaxhighlight>
</lang>
 
=={{header|jq}}==
{{works with|jq}}
 
'''Also works with gojq and fq''' provided the line defining
keys_unsorted is uncommented.
 
In this entry, we adopt an approach which emphasizes
separating code from data: we define a format for
representing state-transition tables as JSON objects,
which can be stored for example in separate files;
and we illustrate one possible FSM engine for
animating such state-transition tables.
 
The format of the JSON object specifying a state-transition table is
as follows, it being assumed that each "state" has a distinct
description as a JSON string:
 
* each top-level key represents a state of the FSM, with "exit" meaning stop;
* the value of each top-level key is another JSON object, which we will refer to as the trigger dictionary;
* each trigger dictionary consists of one or more key-value pairs, in which the "key" is the name of a trigger and the value is the name of a state.
 
Triggers can be of three kinds:
1. external (corresponding to external inputs)
2. automatic (corresponding to determinate internal transitions)
3. indeterminate (corresponding to non-determinism)
 
For external transitions, the keys should be non-empty strings that do not match "^[0-9]+ ".
For automatic transitions, the trigger object should have "" as its only key.
For indeterminate transitions, the trigger object should have keys matching the regex "^[0-9]+ "
 
The FSM engine presented here is intended to allow a person to provide
the "external inputs" as well as to pace automatic transitions and
to simulate the indeterminate transitions. In general, a menu of valid
input choices is presented, and the first match of the response with
these options determines the state transition. In addition, "?" as a
user input is recognized as a request for help.
 
'''fsm.json'''
<syntaxhighlight lang=jq>
{
"ready": {
"deposit": "waiting",
"quit": "exit"
},
"waiting": {
"select": "dispense",
"refund": "refunding"
},
"dispense": {
"confirm": "confirming",
"refund": "refunding"
},
"refunding": {
"1 REFUND MONEY": "ready",
"2 SORRY": "ready"
},
"confirming": {
"": "ready"
}
}
</syntaxhighlight>
'''fsm.jq'''
<syntaxhighlight lang=jq>
# Uncomment the following line if using gojq or fq:
# def keys_unsorted: keys;
 
# next($action) determines the next state.
# Global: $fsm (the transition-table)
# $action specifies an action, which can be abbreviated: the first possible match is selected.
# Input: {state}
def next($action):
($fsm[.state] | keys_unsorted) as $keys
| if ($action|length) == 0
then if $keys|index("") then fsm[.state][""]
else null
end
else (first($keys[] | select( startswith($action) )) // null) as $k
| if $k then fsm[.state][$k] else null end
end;
 
def start: {"state": "ready"};
 
# The FSM engine - progress from state to state based on user input
def progress:
def options: fsm[.state]|keys_unsorted;
def prompt:
options
| if length == 1 and .[0]=="" then "Enter anything to proceed."
elif .[0]|test("^[0-9]+ ") then "options: \(.) (simulated non-deterministic transition)"
else "options: \(.)"
end;
 
def help:
options
| if length == 1 and .[0]=="" then "(internal state transition awaiting your input)"
elif .[0]|startswith("1 ") then "(simulated NDFSM awaiting your input in the form of an initial substring): \(.)"
else
"Make a selection by typing an initial substring of the option you wish to select: \(.)"
end;
 
start
| label $out
| "Initial state: \(.state)\nMake your selection (at least one letter) from these options: \(options))",
foreach inputs as $in (.;
.previous=.state
| .error = null
| if $in == "?" then .error = true #
else next($in) as $next
| if $next then .state=$next else .error = "try again or enter ? for help" end
end;
if .error == true then help
elif .error then .error
elif .state == "exit" then break $out
else
"\(.previous) + \($in) => \(.state)",
prompt
end
) ;
progress
</syntaxhighlight>
'''Illustrative Transcript''':
<pre>
$ jq -nRr --argfile fsm fsm.json -f fsm.jq
Initial state: ready
Make your selection (at least one letter) from these options: ["deposit","quit"])
?
Make a selection by typing an initial substring of the option you wish to select: ["deposit","quit"]
d
ready + d => waiting
options: ["refund","select"]
s
waiting + s => dispense
options: ["confirm","refund"]
c
dispense + c => confirming
Enter anything to proceed.
 
confirming + => ready
options: ["deposit","quit"]
d
ready + d => waiting
options: ["refund","select"]
r
waiting + r => refunding
options: ["1 REFUND MONEY","2 SORRY"] (simulated non-deterministic transition)
1
refunding + 1 => ready
options: ["deposit","quit"]
q
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">abstract type State end
 
struct Ready <: State
Line 961 ⟶ 1,429:
 
runsim(Ready())
</langsyntaxhighlight>{{out}}
<pre>
Vending machine is ready. (q)uit, (d)eposit: d
Line 974 ⟶ 1,442:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.51
 
enum class State { READY, WAITING, EXIT, DISPENSE, REFUNDING }
Line 1,030 ⟶ 1,498:
fun main(args: Array<String>) {
fsm()
}</langsyntaxhighlight>
 
Sample input/output:
Line 1,050 ⟶ 1,518:
OK, quitting
</pre>
 
=={{header|Nim}}==
{{trans Kotlin}}
<syntaxhighlight lang="nim">import strutils
 
type State {.pure.} = enum Ready, Waiting, Exit, Dispense, Refunding
 
 
proc getAnswer(message: string; answers: set[char]): char =
while true:
stdout.write message, ' '
stdout.flushFile
result = (stdin.readLine().toLowerAscii & ' ')[0]
if result in answers: return
 
 
proc fsm =
 
echo "Please enter your option when prompted"
echo "(any characters after the first will be ignored)"
var state = State.Ready
 
while true:
case state
 
of State.Ready:
let trans = getAnswer("\n(D)ispense or (Q)uit :", {'d', 'q'})
state = if trans == 'd': State.Waiting else: State.Exit
 
of State.Waiting:
echo "OK, put your money in the slot"
let trans = getAnswer("(S)elect product or choose a (R)efund :", {'s', 'r'})
state = if trans == 's': State.Dispense else: State.Refunding
 
of State.Dispense:
discard getAnswer("(R)emove product :", {'r'})
state = State.Ready
 
of State.Refunding:
# No transitions defined.
echo "OK, refunding your money"
state = State.Ready
 
of State.Exit:
echo "OK, quitting"
break
 
fsm()</syntaxhighlight>
 
{{out}}
<pre>Please enter your option when prompted
(any characters after the first will be ignored)
 
(D)ispense or (Q)uit : d
OK, put your money in the slot
(S)elect product or choose a (R)efund : s
(R)emove product : r
 
(D)ispense or (Q)uit : d
OK, put your money in the slot
(S)elect product or choose a (R)efund : r
OK, refunding your money
 
(D)ispense or (Q)uit : q
OK, quitting</pre>
 
=={{header|Ol}}==
<langsyntaxhighlight lang="scheme">
(import (scheme read))
 
Line 1,103 ⟶ 1,636:
; run
(state-machine states 'ready)
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 1,135 ⟶ 1,668:
 
</pre>
<syntaxhighlight lang="pascal">
<lang Pascal>
{
fsm1.pas
Line 1,392 ⟶ 1,925:
end.
 
</syntaxhighlight>
</lang>
 
 
Line 1,468 ⟶ 2,001:
=={{header|Perl}}==
Added a dummy input called "IMPLICIT" that does not actually require input but automatically transitions to next state.
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict; # https://rosettacode.org/wiki/Finite_state_machine
Line 1,504 ⟶ 2,037:
waiting REFUND refunding take the refund
dispense REMOVE ready Thank You
refunding IMPLICIT ready</langsyntaxhighlight>
{{out}}
<pre>
Line 1,529 ⟶ 2,062:
 
=={{header|Phix}}==
{{libheader|Phix/pGUI}}
<lang Phix>enum READY, WAITING, DISPENSE, REFUND, QUIT -- (or just use strings if you prefer)
{{libheader|Phix/online}}
 
You can run this online [http://phix.x10.mx/p2js/fsm.htm here].
integer state = READY, ch = ' '
<!--<syntaxhighlight lang="phix">(phixonline)-->
while true do
<span style="color: #000080;font-style:italic;">--
printf(1,"%c\n",ch)
-- demo\rosetta\Finite_State_Machine.exw
switch state do
-- =====================================
case READY: printf(1,"Machine is READY. (D)eposit or (Q)uit :")
--</span>
while true do
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
ch = upper(wait_key())
<span style="color: #000080;font-style:italic;">-- First, let's define our state machine textually, why not:</span>
if ch='D' then state = WAITING exit end if
<span style="color: #008080;">constant</span> <span style="color: #000000;">state_string</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
if ch='Q' then state = QUIT exit end if
Ready,Deposit-&gt;Waiting,Quit
end while
Waiting,Select-&gt;Dispense,Refund
 
Dispense,Remove-&gt;Ready:Remove product
case WAITING: printf(1,"(S)elect product or choose to (R)efund :")
Refund-&gt;Ready:Refunding money
while true do
Quit:Bye
ch = upper(wait_key())
"""</span>
if ch='S' then state = DISPENSE exit end if
if ch='R' then state = REFUND exit end if
<span style="color: #008080;">function</span> <span style="color: #000000;">decode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">state_string</span><span style="color: #0000FF;">)</span>
end while
<span style="color: #004080;">sequence</span> <span style="color: #000000;">states</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
 
<span style="color: #000000;">messages</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
case DISPENSE: printf(1,"Dispensing product...")
<span style="color: #000000;">valid_keys</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
printf(1,"Please (C)ollect product. :")
<span style="color: #008080;">for</span> <span style="color: #000000;">line</span> <span style="color: #008080;">in</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state_string</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
while true do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">state</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
ch = upper(wait_key())
<span style="color: #004080;">string</span> <span style="color: #000000;">keyable</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
if ch='C' then state = READY exit end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">':'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
end while
<span style="color: #000000;">messages</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">messages</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">?</span><span style="color: #000000;">line</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$]:</span><span style="color: #008000;">""</span><span style="color: #0000FF;">))</span>
 
<span style="color: #008080;">for</span> <span style="color: #000000;">phrase</span> <span style="color: #008080;">in</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">m</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #008000;">","</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
case REFUND: printf(1,"Please collect refund.")
<span style="color: #000000;">state</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">phrase</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-&gt;"</span><span style="color: #0000FF;">))</span>
state = READY
<span style="color: #000000;">keyable</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">phrase</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
ch = ' '
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
 
<span style="color: #000000;">states</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">states</span><span style="color: #0000FF;">,</span><span style="color: #000000;">state</span><span style="color: #0000FF;">)</span>
case QUIT: printf(1,"Thank you, shutting down now.\n")
<span style="color: #000000;">valid_keys</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid_keys</span><span style="color: #0000FF;">,</span><span style="color: #000000;">keyable</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$])</span>
exit
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end switch
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">states</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">messages</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">valid_keys</span><span style="color: #0000FF;">}</span>
end while</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
{{out}}
<pre>
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">states</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">messages</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">valid_keys</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">decode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state_string</span><span style="color: #0000FF;">),</span>
Machine is READY. (D)eposit or (Q)uit :D
<span style="color: #000000;">valid_states</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">vslice</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">vslice</span><span style="color: #0000FF;">(</span><span style="color: #000000;">states</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
(S)elect product or choose to (R)efund :S
Dispensing product...Please (C)ollect product. :C
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
Machine is READY. (D)eposit or (Q)uit :D
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vbox</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">state</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">status</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">options</span>
(S)elect product or choose to (R)efund :R
Please collect refund.
<span style="color: #008080;">procedure</span> <span style="color: #000000;">transition_to</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">sdx</span><span style="color: #0000FF;">)</span>
Machine is READY. (D)eposit or (Q)uit :Q
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">status</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">messages</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">])</span>
Thank you, shutting down now.
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">states</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (implicit)</span>
</pre>
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">states</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">valid_states</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid_states</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">])</span>
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">options</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">vslice</span><span style="color: #0000FF;">(</span><span style="color: #000000;">states</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$],</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #008000;">" or "</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">finite_state_machine</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">IupGetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">valid_states</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">cdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid_keys</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">cdx</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">newstate</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">states</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][$]</span>
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">newstate</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid_states</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">transition_to</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid_states</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">`Quit`</span><span style="color: #0000FF;">?</span><span style="color: #004600;">IUP_CLOSE</span><span style="color: #0000FF;">:</span><span style="color: #004600;">IUP_CONTINUE</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">key_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*dlg*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_ESC</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (standard practice for me)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_F5</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (let browser reload work)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">finite_state_machine</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">state</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"EXPAND=YES"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">status</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"EXPAND=YES"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">options</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"EXPAND=YES"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">vbox</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupVbox</span><span style="color: #0000FF;">({</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">status</span><span style="color: #0000FF;">,</span><span style="color: #000000;">options</span><span style="color: #0000FF;">},</span><span style="color: #008000;">`MARGIN=40x40`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vbox</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`TITLE="Finite State Machine",SIZE=200x100`</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"KEY_CB"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"key_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">transition_to</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- Ready</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupHide</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
 
=={{header|PicoLisp}}==
Non-interactive random switch between states.
<langsyntaxhighlight PicoLisplang="picolisp">(seed (in "/dev/urandom" (rd 8)))
(de atm NIL
(state '(ready)
Line 1,592 ⟶ 2,162:
(nil (prinl "quit")) ) ) )
(do 3
(while (atm)) )</langsyntaxhighlight>
{{out}}
<pre>
Line 1,602 ⟶ 2,172:
=={{header|Prolog}}==
 
<langsyntaxhighlight Prologlang="prolog">state(ready, deposit, waiting).
state(ready, quit, exit).
state(waiting, select, dispense).
Line 1,626 ⟶ 2,196:
act(NextState).
print_message(State) :- message(State, Message), format(Message).</langsyntaxhighlight>
{{out}}
<pre>
Line 1,648 ⟶ 2,218:
=={{header|Python}}==
{{works with|Python 3}}
<langsyntaxhighlight Pythonlang="python">''' Finite State Machine for Rosetta Code
Actually two of them. The main FSM described in the task and a second one of the Acceptor variety described on
the WP page to get the input from the user.
Line 1,707 ⟶ 2,277:
if __name__ == "__main__":
finite_state_machine('ready','q')
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,722 ⟶ 2,292:
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
 
(define states
Line 1,752 ⟶ 2,322:
(let/ec quit
(with-input-from-string "deposit select remove deposit refund quit"
(λ () (machine states void read quit)))))</langsyntaxhighlight>
{{out}}
<pre>CURRENT STATE: ready
Line 1,773 ⟶ 2,343:
(formerly Perl 6)
 
<syntaxhighlight lang="raku" perl6line>#===== The state machine =====#
 
class StateMachine {
Line 1,848 ⟶ 2,418:
$machine.add-transition("refunding", "ready");
 
$machine.run("ready");</langsyntaxhighlight>
 
=={{header|REXX}}==
Line 1,862 ⟶ 2,432:
::* a mixture of uppercase and lowercase text is used for the output messages
::* messages have extra blanks for readability &nbsp; (and options are spelled out)
<langsyntaxhighlight lang="rexx">/*REXX pgm simulates a FSM (Finite State Machine), input is recognized by pressing keys.*/
10: say "Press D (deposit) or Q (quit)" /*display a prompt (message) to term. */
20: $=inkey(); upper $ /*since this a terminal, uppercase KEY.*/
Line 1,884 ⟶ 2,454:
 
140: say "Refunded" /*display what action just happened. */
signal 10 /*go & re-start process (ready state). */</langsyntaxhighlight>
{{out|output|text= &nbsp; when using (pressing) the exact same input(s) as the '''BASIC''' entry: &nbsp; &nbsp; <tt> D &nbsp; R &nbsp; D &nbsp; S &nbsp; R &nbsp; Q </tt>}}
<pre>
Line 1,905 ⟶ 2,475:
works withooRexx (and any other REXX).
key and Enter must be pressed-
<langsyntaxhighlight lang="rexx">/*REXX pgm simulates a FSM (Finite State Machine), input is recognized by pressing keys.*/
10: k=inkey('D (deposit) or Q (quit)','DQ')
if k=="D" then signal 50 /*Is response a "D" ? Process deposit.*/
Line 1,932 ⟶ 2,502:
Say 'Invalid key, try again.'
End
Return k</langsyntaxhighlight>
{{out}}
<pre>Press D (deposit) or Q (quit) and Enter
Line 1,946 ⟶ 2,516:
Refunded
Press D (deposit) or Q (quit) and Enter</pre>
 
=={{header|Rust}}==
For abstraction, it is desirable to implement the transitions of the state machine through its methods.
Here it is done transparently using the method_enum::gen macro.<br>
'''[dependencies]'''<br>
methods-enum = "0.2.4"
<syntaxhighlight lang="rust">enum State {
Ready,
Waiting,
Dispense,
Refunding,
Exit,
}
 
#[methods_enum::gen(Act: run)]
impl State {
pub fn set(&mut self);
pub fn input_char(&mut self, ch: char);
 
fn run(&mut self, act: Act) {
match self {
State::Ready => match act {
Act::set() => println!("Ready: d - deposit / q - quit "),
Act::input_char('d') => self.set_state(State::Waiting),
Act::input_char('q') => self.set_state(State::Exit),
_ => self.set(),
},
State::Waiting => match act {
Act::set() => println!("Waiting: s - select / r - refund "),
Act::input_char('s') => self.set_state(State::Dispense),
Act::input_char('r') => self.set_state(State::Refunding),
_ => self.set(),
},
State::Dispense => match act {
Act::set() => println!("Dispense: r - remove "),
Act::input_char('r') => self.set_state(State::Ready),
_ => self.set(),
},
State::Refunding => match act {
Act::set() => {
println!("Refunding: refund of the deposit...");
self.set_state(State::Ready)
}
_ => (), // never - ignore
},
State::Exit => match act {
Act::set() => println!("Exit: goodbye! "),
_ => panic!("!! Invalid command for State::Exit: '{act:?}'"),
},
}
}
 
fn set_state(&mut self, new_state: State) {
*self = new_state;
self.set();
}
}
 
fn main() {
let mut machine = State::Ready;
machine.set();
 
while !matches!(&machine, State::Exit) {
machine.input_char(char_entered());
}
}
 
fn char_entered() -> char {
let mut text = String::new();
std::io::stdin().read_line(&mut text).unwrap_or(0);
text.chars().next().unwrap_or('\x0d')
}</syntaxhighlight>
{{out}}
<pre>Ready: d - deposit / q - quit
d
Waiting: s - select / r - refund
r
Refunding: refund of the deposit...
Ready: d - deposit / q - quit
d
Waiting: s - select / r - refund
s
Dispense: r - remove
r
Ready: d - deposit / q - quit
q
Exit: goodbye!
</pre>
 
=={{header|Tcl}}==
Using a nested dict where the leafs contain the output state corresponding to an action, and empty actions are implicit transitions. Would be marginally cleaner using a do..while proc.
<syntaxhighlight lang="tcl">set fsm [dict create \
ready {deposit waiting quit exit} \
waiting {select dispense refund refunding} \
dispense {remove ready} \
refunding {{} ready} \
]
set state ready
 
proc prompt {fsm state} {
set choices [dict keys [dict get $fsm $state]]
while {1} {
puts -nonewline "state: $state, possible actions: $choices\n>"
if {[gets stdin line] == -1} {
exit
}
if {$line in $choices} {
return $line
}
}
}
 
while {$state ne "exit"} {
set action [prompt $fsm $state]
set state [dict get $fsm $state $action]
while {[dict exists $fsm $state {}]} {
set state [dict get $fsm $state {}]
}
}</syntaxhighlight>
{{out}}
<pre>$ tclsh fsm.tcl
state: ready, possible actions: deposit quit
>deposit
state: waiting, possible actions: select refund
>select
state: dispense, possible actions: remove
>remove
state: ready, possible actions: deposit quit
>deposit
state: waiting, possible actions: select refund
>re
state: waiting, possible actions: select refund
>refund
state: ready, possible actions: deposit quit
>quit</pre>
 
=={{header|VBA}}==
{{trans|Phix}}
<langsyntaxhighlight lang="vb">Enum states
READY
WAITING
Line 2,000 ⟶ 2,705:
End Select
Loop
End Sub</langsyntaxhighlight>{{out}}
<pre>Machine is READY. (D)eposit or (Q)uit :
D
Line 2,020 ⟶ 2,725:
{{trans|Kotlin}}
{{libheader|Wren-str}}
<langsyntaxhighlight ecmascriptlang="wren">import "./str" for Str
import "io" for Stdin, Stdout
 
Line 2,071 ⟶ 2,776:
}
 
fsm.call()</langsyntaxhighlight>
 
{{out}}
Line 2,091 ⟶ 2,796:
(D)ispense or (Q)uit : q
OK, quitting
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">int State, Trans, Table, Msg;
def \State\ Ready, Waiting, Dispense, Refunding, Exit;
def \Trans\ Deposit, Select, Refund, Collect, Quit; \State:
[Table:=[[Waiting, Ready, Ready, Ready, Exit], \Ready
[Waiting, Dispense, Refunding, Waiting, Waiting], \Waiting
[Dispense, Dispense, Dispense, Ready, Dispense], \Dispense
[Ready, Ready, Ready, Ready, Ready], \Refunding
[Exit, Exit, Exit, Exit, Exit]]; \Exit
State:= Ready;
loop [Msg:= ["Ready, choose (D)eposit or (Q)uit: ",
"Waiting, choose (S)elect or (R)efund: ",
"Dispensing, please (C)ollect product: ",
"Refunding, please collect refund.",
"Shutting down."];
Text(0, Msg(State));
case State of
Exit: quit;
Refunding: Trans:= Refund \implicit transition
other case ChIn(1) of \explicit transitions
^D,^d: Trans:= Deposit;
^S,^s: Trans:= Select;
^R,^r: Trans:= Refund;
^C,^c: Trans:= Collect;
^Q,^q: Trans:= Quit
other []; \illegal entries don't change state
CrLf(0);
State:= Table(State, Trans);
];
CrLf(0);
]</syntaxhighlight>
{{out}}
<pre>
Ready, choose (D)eposit or (Q)uit: D
Waiting, choose (S)elect or (R)efund: S
Dispensing, please (C)ollect product: C
Ready, choose (D)eposit or (Q)uit: D
Waiting, choose (S)elect or (R)efund: R
Refunding, please collect refund.
Ready, choose (D)eposit or (Q)uit: Q
Shutting down.
</pre>
 
Line 2,097 ⟶ 2,845:
 
If we need true state to state hops, we could use tail recursion (another name for goto).
<langsyntaxhighlight lang="zkl">class FSM{ // our Finite State Machine
var bank=0, item=Void;
fcn deposit(coin){ bank=coin }
Line 2,112 ⟶ 2,860:
}
 
Vault.add(FSM); // put class FSM where I can find it</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">fcn run(program){ // convert text to FSM instructions and run them
program=program.replace("(",".fp("); // deposit(10)-->deposit.fp(10)
a,b,p := 0,0,Sink("class P(FSM){ state(); ");
Line 2,121 ⟶ 2,869:
// println(program); // WTH did I just do?
Compiler.Compiler.compileText(program)(); // compile and run our little FSM
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">run("select(); take(); deposit(10); select(\"snickers\"); take();");</langsyntaxhighlight>
The above is converted to:
<langsyntaxhighlight lang="zkl">class P(FSM){
state();
act(select.fp());
Line 2,131 ⟶ 2,879:
act( select.fp("snickers"));
act( take.fp());
}</langsyntaxhighlight>
The .fp() is function application (ie deferred execution) so I can extract the
function name and print it.
3,022

edits