| This response is a bit late sorry. I fully agree. Most programming languages already give you enough tools to write very simple and powerful state machines. This works best with languages that have first class support for data literals and maps (or equivalent), such as JS, Clojure, etc. But if you care a ton about performance you can encode the same with say enums and switch statements or similar. It's just a bit more work and you can't change the machines on the fly or generate them from data, which is a very powerful pattern you can put on top of this. But in many cases that's not needed. --- You first define a map of states, where each key is the name of the state and each value is a map from event names to state names. Say you have an on off toggle (very simple example): On => Toggle => Off Off => Toggle => On Where On/Off are state names and Toggle is an event name. Then, you define a map from two states to a function. We call them transition functions. Like so: [On Off] => func()... [Off On] => func()... Inside the functions you would put side-effects directly (such as activating a light or changing a color, sending an email etc.), or maybe just describe side effects so another part of your program can handle them (which can be useful with larger programs as it makes testing easier). Lastly, you define a state machine function that runs your program like so: func(state, event) => if event is handled: trigger transition function and return new state, else: return current state In many cases you want to simply ignore events that aren't handled in the current state of your state machine (like described above). Sometimes though, you want to buffer events that are currently not handled in a queue and handle them later; that's a niche use-case in order to manage async events in a specific order. |