Dynamic hierarchical state machines with statig

  Рет қаралды 6,544

chris biscardi

chris biscardi

Күн бұрын

Пікірлер: 25
@vithuransoccer1
@vithuransoccer1 2 жыл бұрын
This is pretty cool it kind of lets you define side effects in a state machine, which is usually a feature of OOP languages but this methodology kind of defines a functional programing paradigm with side effects.
@chris.davidoff
@chris.davidoff 2 жыл бұрын
13 hours ago? That's so 13 hours ago
@danielegvi
@danielegvi 2 жыл бұрын
This is 13 hours ago
@porky1118
@porky1118 2 жыл бұрын
1:22 For now it sounds like Rust enums. They can have state and can be nested.
@cemgecgel4284
@cemgecgel4284 2 жыл бұрын
Superstates looks like inheritance. I think they have the same limitations of inheritance. It whould have been a lot better to just not get into superstate and leave the user alone. The user can always put the similar functionality into a function an call that function rather than delegating to a superstate. Multiple states can call the same function, which is equivalent to them having the same superstate. However, now, the state can call multiple function as it wants, which is similar to a state having multiple superstates, which is not possible in the library as I understood.
@chrisbiscardi
@chrisbiscardi 2 жыл бұрын
This library is for modelling state machines and the transitions between them, so you wouldn't use it for any sort of "cat and dog are both animals" kind of use cases. What you're basically getting here is a tree data structure with a single activated path of nodes to an edge node and a way to control transitions from that path into other paths.
@cemgecgel4284
@cemgecgel4284 2 жыл бұрын
@@chrisbiscardi In the end, the superstate is just for reducing code duplication, which should be done using functions. "K is the superstate of A and B" is same as "cat and dog are both animals." And I assure you, at some point you will need "K and L are superstates of A, K and M are superstates of B", which is not possible because multiple superstates are not allowed, and even if they were allowed that will lead to problems like diamond of death. Parallel to inheritance is clear here, superstates are used for reducing duplicated code, which is a bad idea. Functions should be used for reducing duplicated code. This leads to "A and B calls function K in their implementation", which can very naturally expanded to "A calls functions K or L, B calls functions K or M in their implementation."
@chrisbiscardi
@chrisbiscardi 2 жыл бұрын
@Cem GEÇGEL I would encourage you to research this topic a bit deeper. This tool isn't for calling functions on a shared parent.
@cemgecgel4284
@cemgecgel4284 2 жыл бұрын
@@chrisbiscardi Calling a function is just an implementation detail about the state logic. I will explain better with an example. Imagine there are two states we care about: working and waiting. Every second a timer event happens and occasionally a task event happens. When in working state: - on timer event: decrease the counter and switch to waiting state if it becomes 0. - on task event: crash. When in waiting state: - on timer event do nothing. - on task event: set the counter the value carried by the task event, set the led green and switch to working state. Then, the specifications change and we need a repairing state. A repair event is dispacted and we need to go the repair state and need to set the led to yellow. Now this logic must be added to both working and waiting states as given below: When in working state: - on timer event: decrease the counter and switch to waiting state if it becomes 0. - on task event: crash. - on repair event: set the led yellow and switch to repairing state. When in waiting state: - on timer event do nothing. - on task event: set the counter the value carried by the task event, set the led green and switch to working state. - on repair event: set the led yellow and switch to repairing state. But we see that as duplication of code, which is bad. Thus, we create a superstate called non-repairing state: When in non-repairing state: - on timer event: crash. - on task event: crash. - on repair event: set the led yellow and switch to repairing state. When in working state, which is a substate of non-repairing: - on timer event: decrease the counter and switch to waiting state if it becomes 0. - on task event: crash. - on repair event: delegate to superstate. When in waiting state, which is a substate of non-repairing: - on timer event: do nothing. - on task event: set the counter the value carried by the task event, set the led green and switch to working state. - on repair event: delegate to superstate. Then, specifications change again and we need an error state rather than a hard crash on error. Only the working state or repairing state can switch to error state, by the specification errors should not be happening in the waiting state. Hence, using a similar style, we create a non-error state. But we reach a wall, as the states cannot have multiple super-states. Solution is using functions for code deduplications. Here the state machine is not built for calling a function. Just that we need to implement the state logic and inside that logic we can call functions for code deduplication. We do not need the non-repairing state anymore. There are solely working, waiting, repairing and error states. Function switch_to_repairing: set the led yellow and switch to repairing state. Function switch_to_error: set the led red and switch to repairing state. When in working state: - on timer event: decrease the counter and switch to waiting state if it becomes 0. - on task event: call switch_to_error. - on repair event: call switch_to_repairing. When in waiting state: - on timer event: do nothing. - on task event: set the counter the value carried by the task event, set the led green and switch to working state. - on repair event: call switch_to_repairing. Benefits: - no need to create superstates, which are abstract and hard to understand, - no need to have infrastructure and API in the library for superstates, - delegation is explicit and no need to have super state crash on invalid events delegated to it; it does not care about event it cannot handle because it's job is not handling events, - and, the best thing, the function only knows its own purpose, which is settings up the stage for the repairing state. These criticisms are the same as what is given to inheritance. Because idea of a superstate is very similar to a supertype. Furthermore, the mechanism of delegating to a superstate is clearly the same as delegating to a superclass (for example, in Java with `super.doIt()`). Solution is clear, just do not have superstates in the library. User can call a function when there are duplications in code. Hope this clarifies what I'm trying to say.
@jarrednorris
@jarrednorris 2 жыл бұрын
This could be a dumb question (i'm a rust and bevy newbie), but I'd be intrigued to know how/if this library could work well within bevy, for example creating a heirarchical state based character controller in a bevy game, in my experience these types of character controllers are really nice to develop with and it would be nice to explore if that was a viable option. Might not work well at all with the ecs nature of bevy however
@wumwum42
@wumwum42 2 жыл бұрын
I didnt dive that deep into bevy, but I am quite sure bevy has a similer built-in way of doing this with component structs, Maybe ask in the bevy discord for examples.
@chrisbiscardi
@chrisbiscardi 2 жыл бұрын
This is one of the use cases I plan on exploring with this crate, so we'll find out how well it works :)
@uwuzote
@uwuzote 2 жыл бұрын
I guess you can do ResourceMut of it
@JeffHanke
@JeffHanke 2 жыл бұрын
Reminds me of redux a bit, I wonder if/how it could integrate with reactive libraries.
@chrisbiscardi
@chrisbiscardi 2 жыл бұрын
I'm definitely interested in finding a state machine library to mirror what xstate has done in the JS ecosystem. statig is an interesting crate to try for this. Typestate might be better for UI components due the the way events can return errors that can be handled.
@maniacZesci
@maniacZesci 2 жыл бұрын
Can we have local storage for state as well as access to the context values? Something like this: #[state] fn on(&mut self, counter: &mut u32, event: &Event) -> Response { }
@chrisbiscardi
@chrisbiscardi 2 жыл бұрын
The State struct does actually contain the data for the enums for each state. . so State::On would have a counter field, and superstates would get references to that field. It's useful to either expand the macros in your editor for the examples, or to compare the macro and non-macro examples to see what code is being generated. For example, the Blinky no_macro example shows what the State would look like: github.com/mdeloof/statig/blob/063888873c901660b2391ac826b1d88096d81718/examples/no_macro/blinky/src/main.rs#L10-L13
@maniacZesci
@maniacZesci 2 жыл бұрын
@chris biscardi Thanks, I saw that part you linked but haven't figured it out yet. So if i assume correctly when written like this: #[state] fn message_sent(&mut self, counter: &mut u32, event: &Event) -> Response { } #[state] fn message_received(&mut self, counter: &mut u32, id: &u32, event: &Event) -> Response { } macro parses method arguments between first one "&mut self" and last one "event: &Event" or from the first one to the one before last if context is omitted. So in this case Enum generated would be: pub enum State { MessageSent { counter: isize}, MessageReceived { counter: isize, id: isize }, } If I understand it correctly? In that case thing to remember is that event argument always comes last.
@chrisbiscardi
@chrisbiscardi 2 жыл бұрын
@@maniacZesci you do understand that correctly with respect to the macro expansion and what State would be. The only difference is that the order of the Event doesn't matter in the arguments. The macro seems to be insensitive to the position of the arguments. The implementation of the anayze_state portion of the macro can be found here: github.com/mdeloof/statig/blob/18d5b34207f5d9e2492e52e691addd93992781a5/macro/src/analyze.rs#L280
@wanderingthewastes6159
@wanderingthewastes6159 2 жыл бұрын
What’s your opinion on the typestate crate? Is it any good for implementing FSMs in Rust?
@chrisbiscardi
@chrisbiscardi 2 жыл бұрын
the typestate crate is an interesting crate. I think the major difference between statig and typestate is that typestate expects that you'll call a function for a transition and your program will handle an error if it happens, whereas statig doesn't return a value after handling events so can be used in situations where the inputs are a bit looser. typestate is a traffic light's logic and statig is user input handling. of course this is just a rough comparison and there's nothing preventing you from actually taking one crate and using it in the other way.
@larrymarso4492
@larrymarso4492 2 жыл бұрын
You are zoomed in so close, it's hard to see context and follow along. Far beyond what's needed for readability.
@chrisbiscardi
@chrisbiscardi 2 жыл бұрын
I'll keep that in mind for future videos. I do have people that watch on their phones but I could go smaller than this video I think.
@larrymarso4492
@larrymarso4492 2 жыл бұрын
@@chrisbiscardi I watched on a phone. Your previous videos are fine on the phone.
@negvorsa
@negvorsa 2 жыл бұрын
I liked this text size ...I'm on 7" device!!
SolidJS in Rust with Sycamore
7:22
chris biscardi
Рет қаралды 7 М.
When Booleans Are Not Enough... State Machines?
21:50
Next Day Video
Рет қаралды 26 М.
24 Часа в БОУЛИНГЕ !
27:03
A4
Рет қаралды 7 МЛН
Who is More Stupid? #tiktok #sigmagirl #funny
0:27
CRAZY GREAPA
Рет қаралды 10 МЛН
Improve your Rust APIs with the type state pattern
14:45
Let's Get Rusty
Рет қаралды 92 М.
How NES Games Use State Machines For Everything
8:21
NesHacker
Рет қаралды 37 М.
Finite State Machines in Godot 4 in Under 10 Minutes
7:16
Bitlytic
Рет қаралды 333 М.
Computers Without Memory - Computerphile
8:52
Computerphile
Рет қаралды 339 М.
Code Class - Hierarchical State Machines
29:41
AdamCYounis
Рет қаралды 23 М.
Generic Traits, Impls, and Slices in Rustlang
18:05
chris biscardi
Рет қаралды 11 М.
Do This Instead Of Representing State With Booleans
12:23
Joy of Code
Рет қаралды 116 М.
A-Level Comp Sci: Finite State Machine
8:21
justAlevel
Рет қаралды 108 М.
24 Часа в БОУЛИНГЕ !
27:03
A4
Рет қаралды 7 МЛН