Live data from Hacker News

State Machines in Rust

blog.yoshuawuyts.com

11–20 of 119 posts

Re: State Machines in Rust

#11
I disagree with the implementation, State should be a trait with NextState as an associated type. This makes things cumbersome when it can be a set of types, but it makes excellent use of the type system and ownership patterns of Rust. Edit: and the type state pattern http://cliffle.com/blog/rust-typestate/

As an aside, if you want to dive in with FSMs and automata theory (as well as some basic language topics) go read Sipser's book, "Introduction to the Theory of Computation." You'll go from logic to state machines to understanding why Turing Machines are so dope in a few dozen pages. The math isn't bad.

Re: State Machines in Rust

#12

However one big limitation of this is that this pattern cannot store the state inside another struct; it can only exist on the stack this way. So we cannot do the following: struct Foo { state: State , } The moment we initialize Foo to take e.g. Green as its parameter, it can now no longer switch to Red in safe Rust. This is what enums are for, and unfortunately we can't use those here. Couldn't you just declare a tr…

Yes, this is basically erasing type invariants by moving them into runtime code. Similar things have been done with things like GPIO pins in embedded code, having the pin numbers carried in the type (`struct Pin1;`) and being able to erase those for collections by moving them to runtime (`struct Pin { id: u8 }`). Unfortunately it comes with a bunch of extra implementation overhead currently, maybe in the future with const-generics it would be possible to reduce this overhead (that would end up being closer to some sort of merge between the first example and the "future directions") .

Re: State Machines in Rust

#13

I disagree with the implementation, State should be a trait with NextState as an associated type. This makes things cumbersome when it can be a set of types, but it makes excellent use of the type system and ownership patterns of Rust. Edit: and the type state pattern http://cliffle.com/blog/rust-typestate/ As an aside, if you want to dive in with FSMs and automata theory (as well as some basic language topics) go re…

See Nemo157's response to cerebellum42. He explains why having this in runtime is not the best approach for FSMs.

Re: State Machines in Rust

#15

Advocating for programmer ergonomics is always a good thing. And I think more people should advocate and try to design languages in such a way that the way of programming more closely resembles the actual real thing [1, 2]. As you might recall in cognitive psychology there's a specific idea that translating a problem to a more recognizable problem (or simply changing the symbols) is a good thing [3]. Having less work…

While I love Bret's work I don't think that's scalable. If you can simulate time axis, it means it can simulate only systems that can are hundreds of times smaller than system resource. E.g. can you simulate a Kubernetes swarm with thousands of different settings?

It's a great learning tool, but not much else.

Re: State Machines in Rust

#16
C++20 supports enums as non-type template parameters, so I think it'd be possible to do it with enums there. Something like:

    enum class Color{Green, Yellow, Red};

    template
    struct State{};

    auto newState() -> State  {...};

    auto next(State) -> State {...}

    auto next(State) -> State {...}

    auto next(State) -> State {...}

    int main(){
      const auto state = newState(); // Green
      const auto state = next(state); // Yellow
      const auto state = next(state); // Red
      const auto state = next(state); // Green
      const auto state = next(state); // Yellow
    }

Re: State Machines in Rust

#17
post #7

However one big limitation of this is that this pattern cannot store the state inside another struct; it can only exist on the stack this way. So we cannot do the following: struct Foo { state: State , } The moment we initialize Foo to take e.g. Green as its parameter, it can now no longer switch to Red in safe Rust. This is what enums are for, and unfortunately we can't use those here. Couldn't you just declare a tr…

The cited post[1] recommends an enum for this job, which avoids the dynamic dispatch and makes it easier to get at a specific state’s data when you have the whole machine. [1] https://hoverbear.org/blog/rust-state-machine-pattern/

I am not a fan of the hoverbear state machine pattern. I find that it makes simple things complicated and hard things impossible. I used it and I had problems with:

  - Reusing code between states.
  - Making callbacks to other APIs during state changes.
I ended up using the standard state pattern described here: https://doc.rust-lang.org/book/ch17-03-oo-design-patterns.ht...

The state pattern is not considered to be idiomatic Rust, but in my experience it works better and is very flexible.

The state pattern has the downside that the type system does not enforce which state changes are allowed.

Re: State Machines in Rust

#18
post #4

Once upon a time I have implemented POP3 server protocol state machine in Clojure. 180 lines in total, of which 40 were FSM declaration, 140 command handling functions. Not sure I'll ever want to approach FSM in any other language, unless no other choice.

Can you perhaps point to it? Sounds interesting to read that code!

Re: State Machines in Rust

#19

I disagree with the implementation, State should be a trait with NextState as an associated type. This makes things cumbersome when it can be a set of types, but it makes excellent use of the type system and ownership patterns of Rust. Edit: and the type state pattern http://cliffle.com/blog/rust-typestate/ As an aside, if you want to dive in with FSMs and automata theory (as well as some basic language topics) go re…

See Nemo157's response to cerebellum42. He explains why having this in runtime is not the best approach for FSMs.

Nothing I suggested implies a runtime penalty. Quite the opposite actually.

Re: State Machines in Rust

#20

However one big limitation of this is that this pattern cannot store the state inside another struct; it can only exist on the stack this way. So we cannot do the following: struct Foo { state: State , } The moment we initialize Foo to take e.g. Green as its parameter, it can now no longer switch to Red in safe Rust. This is what enums are for, and unfortunately we can't use those here. Couldn't you just declare a tr…

Of course dynamic dispatch helps, but using it for a state machine is going to raise eyebrows and kill performance.

I think this would depend on the application. Its possibly a problem in a parser of large data, but in a network protocol or business rule its not going make any difference at all.
Post reply on HN