[HN Gopher] Show HN: State Trooper - Tiny, no frills state machi...
___________________________________________________________________
Show HN: State Trooper - Tiny, no frills state machine for Go
Needed to isolate a bit of DRY logic for some of my projects. Might
be of use to others out there.
Author : hishamk
Score : 76 points
Date : 2023-06-17 14:21 UTC (8 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| naikrovek wrote:
| I am actually angry at how good the project name is.
| jnordwick wrote:
| I've written 2 in C++ for different projects at companies State
| Farm and State of Decay. I'm trying to write one that kind of
| inverts things and calling it Enemy of the State.
|
| But yes, his name pisses me off because I didnt think of it
| either.
| easeout wrote:
| May I suggest for a logo: A directed graph in the form of a
| sheriff's star badge
| icyfox wrote:
| Midjourney actually does pretty well with this one (needs a bit
| of cleanup but shockingly useful as a first draft):
| https://imgur.com/a/GKzx3vX
| hishamk wrote:
| Ha! Not bad at all.
| [deleted]
| klabb3 wrote:
| I saw the benchmark which seemed crazy (3us per transition and
| allocations). So looked quickly at the code.
|
| Recommend putting the tracking of previous states in a separate
| optional debugging type so you don't have to pay the cost in
| general. Oh and using time stamps as a key is kinda weird, but
| even weirder in Go where maps are non-deterministically
| enumerable.
|
| Otherwise, seems like a good use of generics, given Golangs
| particular take on it.
| victorbjorklund wrote:
| Great name!
| hishamk wrote:
| Thank you!
| earthboundkid wrote:
| A state machine should have more than states. It also needs
| _actions_ which cause transitions. The API should be about
| writing out which new state an action causes given a base state.
| Eg you have a modal with a button and it can be clicked or
| dismissed. In the open state, click and dismiss cause close, and
| in the closed state, click causes open. Anyway, the whole thing
| is only valuable once you have actions.
| packetslave wrote:
| Commenters like you are why people don't share thing. Why make
| something available _for free_ when someone like you is just
| going to come along and shit on it?
| akira2501 wrote:
| If your only reasoning behind releasing an open source
| project is to receive uncritical accolades just for producing
| open source, then I think you need to examine your motives
| and seriously question why you expected this deference in the
| first place.
| [deleted]
| jawr wrote:
| Commenters like you are why people don't give honest
| feedback. Why review something for free when someone like you
| is unable to accept honest feedback even if it is critical.
| BSEdlMMldESB wrote:
| you mean like:
|
| > Add valid transitions between states:
|
| > `fsm.AddRule(CustomStateEnumA, CustomStateEnumB)`
|
| > `fsm.AddRule(CustomStateEnumB, CustomStateEnumC)`
| Someone wrote:
| I don't like that name.
|
| IMO, _AddValidTransition_ would be way better. I think I
| would go for _AddTransition_ , though. It's not as if there's
| also a way to add invalid transitions.
| infogulch wrote:
| They should be named and other transitions disallowed.
| bsaul wrote:
| enums with associated values (like in swift) really are the thing
| i miss the most in go.
| pjmlp wrote:
| Yeah, yet another Algol 60 missing feature.
|
| I really don't get how one can suggest the iota const dance
| with a straight face as an alternative.
| rochak wrote:
| The sooner you realise Go is just C with some niceties, the
| better.
| pjmlp wrote:
| When are C enumerations coming to Go?
| pokstad wrote:
| Looks cool. It'd be nice if you could output the FSM to some kind
| of diagram markup (plantuml or mermaidjs).
| syngrog66 wrote:
| A state machine (specifically a FSM) class is something I end up
| having to reinvent in every new language I've adopted. Such a
| useful pattern whose need comes up repeatedly. Especially in
| games/sims or in anything with a GUI. Since I've been making both
| for decades I have a lot of homegrown FSM classes sitting around.
| :-p
| samsquire wrote:
| I am working on a state machine formulation/notation that can
| be executed.
|
| The runtime is multithreaded and parallel.
|
| The idea is to execute the following state machine:
| thread(s) = fact(variable) | send(message) | receive(message2);
| thread(r) = fact(variable) | receive(message) | send(message2);
|
| This program waits until thread(s) is true in another thread
| until thread(r) is true, everything left of the equals symbol
| needs to be true before it passes to the next group of facts
| after the = symbol. Then it waits for "fact(variable)" to be
| fired, then when all those atoms are true, the state
| transitions past the pipe symbol and does a send(message) while
| the other thread does a receive(message) and then the process
| is repeated in the opposite direction. I've not shown it here,
| but you can wait for multiple facts to be true too.
|
| Here's a state machine for an (echo) server that is intended to
| be mapped to epoll or libiouring: accept | {
| submit_recv! | recv | submit_send } { submit_send! | send |
| submit_recv }
|
| The curly brackets means parallel state machines that run
| independently, like a fork.
| syngrog66 wrote:
| love it! shutup and take my money/adoption/usage/attention!
| ha
|
| no but seriously, sounds like a good/useful plan/approach.
| please let me know if you share out a spec or impl sometime
|
| BONUS points for a Golang or C lib
| syntheweave wrote:
| That is a description of flow-based programming, minus the
| generalization to "arbitrary packets of data in bounded
| buffers" - that is, your only data type is true/false and
| your only buffer size is 1, which lets you get some very
| clean syntax on it. It's a good invention!
|
| FBP adapts the physical concept of unit record machines that
| operate over punchcard stacks, which predisposes it to
| thinking in terms of processing and transforming richer data
| like "characters in a string" or "records in an array", but
| it basically works for truth-signalling logic too - let truth
| packets wait in a buffer, and then when the node signals that
| the packets are able to move, that is the transition.
|
| The emphasis does differ in that if we are thinking "FSM",
| the rest of the program and the data it handles have been
| abstracted, while if we are thinking "FBP" we're engaged with
| designing specific machines to connect together in terms of
| I/O, which is more helpful when you have a library of data
| operations to reuse.
| whywouldudothat wrote:
| [dead]
| preseinger wrote:
| func (fsm *FSM[T]) Transition(...) { ...
| fsm.Transitions[time.Now()] = Transition[T]{
| FromState: *fsm.CurrentState, ToState: targetState,
| Timestamp: &tn, Metadata: metadata, }
|
| does fsm.Transitions grow without bounds?
| wahnfrieden wrote:
| [flagged]
| Solvency wrote:
| Rust - A memory safe programming language
|
| wahnfrieden: Why the iron oxide name? Besides the fact that
| it's a pun. Is the code written with it always bound to be
| rusty and old?
| wahnfrieden wrote:
| [flagged]
| MobileVet wrote:
| Nice work!! I have always appreciated the clarity of FSMs since
| first learning about them in college. They are a great way to
| think about a system's state and given X input, clearly define
| the next state. This makes them very easy to test as well.
| giraffe_lady wrote:
| [flagged]
| brigadier132 wrote:
| This would be hilarious if it was satire
| giraffe_lady wrote:
| [flagged]
| Anon_Forever wrote:
| [flagged]
| [deleted]
| oofta-boofta wrote:
| Tell me your a DEI Director without actually telling me you're
| a DEI Director.
| giraffe_lady wrote:
| Nah just a guy who had some teeth knocked out by the state
| police.
| jupp0r wrote:
| Nice job. In my own usage of state machine libraries over the
| years I have found that for complex use cases, it's definitely
| helpful to have event-based transition dispatching be part of the
| library. The great benefit of FSMs is that you can express in
| data a lot of aspects that you would normally express in code.
| Not knowing what event needs to happen to transition to one state
| vs another leaves out a lot of the benefits that you get from
| designing your code around FSMs.
|
| That being said, I appreciate the simplicity and it's a totally
| fine choice to leave out event based dispatch for less complex
| use cases!
|
| One thing that has been mentioned here already: it's super
| helpful to have your library output a diagram file to visualize
| the FSM. This is a really great way to keep code and
| documentation in sync always.
| hishamk wrote:
| Thank you. The focus was on simplicity and handling less
| complex scenarios. In my current projects the business logic
| lends itself to sitting outside the FSM/State Trooper. The
| logic dictates the transitions at arms length to the FSM. The
| FSM does not carry on any particular business logic, it just
| enforces the transition rules from one state to any number of
| possible states - hence why I've included the metadata aspect
| to embed info about the reason for a transition.
|
| Re the visualization, I think that would be cool. I might give
| that a shot.
| rowls66 wrote:
| Interesting. I wrote almost the same code for work a couple of
| weeks ago.
|
| Not sore, but it looks like the Transition function has a race
| condition. It calls CanTansition() before acquiring the mutex
| lock. I think this could lead to illegal state transitions.
| hishamk wrote:
| Thanks for this. You are indeed correct. I've pushed a fix and
| also added a race test to confirm the fix.
___________________________________________________________________
(page generated 2023-06-17 23:01 UTC)