30 comments

[ 10.1 ms ] story [ 57.4 ms ] thread
State Machines, also called runtime programs.

I think when people call it "State Machines", it's for when they know the slightest breeze will trip it up. It's so seductive, because your initial use case gets resolved fairly quickly..

Ironically, the places they have worked wonders, is actually game engines from early 90's, where they have specific design, purposes, and limitations.

They work well for protocols too!
A reasonably powerful subset of regex is a state machine.
State machines don’t need to be runtime programs.

They can be expressed exactly using a static type system - that’s kind of exact the proposition of them.

The idris book opens with a section on dependently-typed state machines and it’s magnificent.
What book is this?
Type driven development with idris
I feel I've read a number of pieces on programming that talk about the evils of if statements (on which I more or less agree) and advocating their replacement by state machines. However I've never seen a super simple implementation of this that seems to obviously fulfill most branching use cases. The closest is the state/strategy pattern, which is great but if patterns (as it's sometimes said) reflect deficiencies in a language, what would a language with first-class state machines look like?
VHDL is close. If you define nextstate logic (logic expression that determines next state based on current state and current input) and nextstate latch (that transfers calculated next state to current state register) it gets recognized as finite state machine and optimized by the synthetizer.
State machines are pretty simple in rust. Pseudo code to get the gist:

  state = match (state, event) {
    (State1, Event1) => {
       State2
    }
    (State1, Event2) => {
       ...
    }
    ...
  };
Does this end up replacing a large portion of if/else or switch statements?
This is basically a switch statement :)
If it evaluates top to bottom in an order-dependent fashion then I suppose so. If it is order independent then it's more like what I want from a state machine.
What exactly are you looking for wrt to "order independent". Like, this will compile down to a computed jump table if that's what you're getting at.
Insert new cases or change order without affecting behavior and statically check that all cases are covered. Unlike a switch statement or if else block where each condition is checked in order so adding more cases gets difficult.
All Rust match statements as statically checked that all cases are covered by the compiler; you can't really turn that of even with unsafe blocks.

How are you expecting that inserting or adding statements would change behavior?

On a level you've just shown they're pretty simple in nearly any language. I do use state machines quite often in my code but mostly on a different level. Multiple threads communicating to each other via home grown PS bus
The ADTs of state and event let you encode the validity of access to data, and whether you've fully enumerated your state/event tuples in a way that isn't available in a lot of languages typically used when writing state machines.
Sounds like you're trying to "scare me" into language. I have what I believe is superior implementation and have no problem counting states. Thank you but I am fine. It is not that I am against the Rust. Rich ecosystem is always good. Personally however I feel no real need for Rust at all. I understand that it is trying to be better C++ but frankly with modern C++ its libraries and tooling I've got enough safety features up to my gills. I do not remember when was the last time my products had memory leak, overrun etc. I do use bunch of other languages but so far had zero reason to use Rust. I live off my own products or products I create for other companies on contract basis and from that perspective adding yet another language would not earn me one extra penny. Rather quite the opposite.
That's a really defensive response. I'm not telling you to do anything or trying to "scare you". I was literally just saying how it has been helpful to someone who previously was a lead on a C++ RTOS and wrote a lot of state machines, both in C++ and in Rust.
That's a really defensive response. I'm not telling you to do anything or trying to "scare you"

It sure sounded this way (trying to scare) to me but if I am wrong please accept my apology. Besides I did say "sounds like" ;)

> I do not remember when was the last time my products had memory leak, overrun etc ...

That you know of.

Stack and heap corruption have this nasty habit of surviving for weeks/months/years until the layout of something completely different changes and the whole thing comes crumbling down.

As a practical being often paying for product development phase myself I tend to worry about things that pose the actual problem. I'll worry about the "whole thing crumbling down" when/if it ever comes. As far I concern in my about 40 total years of experience it did not happen. If it happens to some other developers - not my problem.
C++ isn't even 40 years old but if you've got some secret technique that has eluded modern software engineering then by all means feel free to share it with the class.
Did I ever say that I only develop in C++? As for tech I did say that modern C++/libs/tooling supply more than enough safety features. If you do not know what those are please do feel free to educate yourself
Using generic methods in lisp worth eql keyword for state change is a natural way of doing this.
While there are less of these now (possibly because of the feature described here), if you find a store with an automatic door that swings out, standing on the pad that is outside to block the door from moving is a good way to annoy your friends who are behind you and teach them about simple state machines.
Another common one (at least once upon a time) is the coin-operated turnstile, which is basically (ab)* where a is inserting a coin and b is rotating.
Eat, work, sleep, repeat is already a state machine