State Machines
blog.markwshead.com
blog.markwshead.com
I am reminded of a particularly interesting DSL[1] for Forth that makes state machines look like their transition tables:
4 WIDE FSM: <Fixed.Pt#>
\ input: | other? | num? | minus? | dp? |
\ state: ---------------------------------------------
( 0 ) DROP >0 EMIT >1 EMIT >1 EMIT >2
( 1 ) DROP >1 EMIT >1 DROP >1 EMIT >2
( 2 ) DROP >2 EMIT >2 DROP >2 DROP >2 ;
[1]http://galileo.phys.virginia.edu/classes/551.jvn.fall01/fsm....I used nested C# Enumerators to implement a parser which didn't turn into too much of a mess, but it was a small project.
Structured programming limits you in the state machines you can construct, but probably in a good way.
it's fairly simple syntax, using goto's.
The state machine would look something like this:
(define a
(automaton init
(init : (c -> loop))
(loop : (a -> loop)
(d -> loop)
(r -> end))
(end : )))Compact and efficient state machines are immensely useful when working with small microcontrollers that don't even run an OS.
Yes, though tail call optimization will allow also handle this problem well.
TBB isn't NUMA-aware though, which limits its use in HPC.
[1] http://software.intel.com/en-us/blogs/2011/09/08/the-intel-t...
State transitions can manipulate the stack, and the top of a stack can be used to pick which state to move to.
PDAs aren't as powerful as Turing machines, but they are able to parse any context free grammar, so they are able to recognize languages that contain any number of 'a' characters followed by the same number of 'b' characters.
To be complete, _non-deterministic_ PDAs can recognize any context-free language. Afaik you can't use a normal, deterministic parser to recognize things like the language of all palindromes (which is context-free).
State Machines described in ordinary mathematics have other advantages. For example, substitution distributes over operators in mathematics (but not in most programming languages). This is very handy for deriving an implementation from a specification. Another example is that composition can be treated uniformly by using a single state space for all State Machines.
If you are interested in the applications and advantages of describing computation by State Machines you may like reading the works of Leslie Lamport [2] or texts about the ASM method [3].
[1] https://research.microsoft.com/en-us/um/people/lamport/pubs/...
http://www.udacity.com/overview/Course/cs262/CourseRev/apr20...
I've encountered such code many times in our codebase.
Or maybe you used some business process engine (like jbpm) - that's also state machine.
I've even made jbpm-like engine in javascript for my html5 game - I use it to write quests in my game, and I plan to refactor dialog trees to also use it.
It's graph with nodes and transitions, nodes specify actions game should do, transitions specify conditions player has to do to move to next node.
Here's code if anybody's interested: https://github.com/ajuc/pefjs
And here's graphical editor for graphs: https://github.com/ajuc/jsDotForPefjs
Here's an example where the author manages comet connections using gen_fsm in Erlang:
http://www.letsyouandhimfight.com/2010/01/31/comet-in-erlang...
The FSM starts in state "waiting" (waiting for a connection/request). When a request arrives, the state is transitioned to "have_request". When/if a packet arrives when there's a request connected (packet -> have_request), the data is sent to the client (that then disconnects; the nature of this comet implementation) and the next state is set to "waiting". When a packet arrives when the current state is "waiting", it's added to a buffer and the next state is set to "have_packet". When a request is made and the state is "have_packet" - as opposed to when it was in "waiting" - the packet is immediately sent to the client, and the next state is set to "waiting". There are many other states and "events" in the code, but I think this illustrates how easy FSMs make it to reason about these kind of implementations (protocols).
OLTP software, network stacks, computer games, object based simulations and so on are all good examples of things that you could probably implement a lot easier using state machines than you could ever implement them using some other coding technique (likely you'd be re-implementing state machines anyway, just not by name and in a warped form).
Statemachines get rid of the endless series of flags and ugly error handling that would otherwise govern a re-start of a chunk of code at a later date without assigning a thread to each datum that passes through the system.
But when code does profit from a state machine, it's often easy to recognize from the many 'if' statements that check several flags (like ' if (seen_input && !eof && ..)')
This is great thread. I have only used lex/flex to make my state machines. I'd like to try something new eventually.
[1] http://www.ioreader.com/2011/03/15/pattern-matching-in-grail