-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework statemachine #139
Rework statemachine #139
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's off to a very strong start! Feels like 80% there. These could also be used to power the frp stream library I'm slowly working on so I'm looking forward to having this merged.
What are your feelings towards renaming it from new-statemachine
to statemachine2.fnl
and merging it when the API + tests are done, then replacing the old library with it in a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests look good, only minor copy changes
There is no timeout state so the name makes no sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Nice job! Will let it sit to give Ag time to take a look before merging.
We want to do this so that once we leave an app the state of the machine has :app set to nil, otherwise the modal menu will continue to display items from the previous app. Because we are still firing an effect, we need to guard around the effect handlers, doing nothing when we have an enter or launch effect but no app.
Thoughts on renaming |
Yeah, I do too, feel that "signal" is a bit ambiguous - "is it a noun; a verb?". "Send" doesn't seem to be a great fit here either. I think what we're looking for is the equivalent for "emit", and "emit" and "broadcast" feel a bit too pretentious to me. We're not dealing with a distributed database of some sort, right? I started looking for synonyms, and all that I could come up with, are a bunch of lousier variants. Things like: communicate, convey, deliver, emanate, enunciate, percolate, radiate, promote, propagate Maybe, keeping up with the tradition of Lisp, we should use something bare elemental? Something like "shout" or even "yell"? 😆 They say "naming is the hardest thing in software". Naming itself may not so much, but explaining to other people why a particular name was chosen - that's tough. |
transmit? I agree |
Agreed. Don't want to bikeshed too much on it, but names have their importance too. The reason I brought this up was because upon reviewing the code again I didn't recognize it. I proposed It seems to me |
I was thinking of what would be the term used in finite automata theory, and I couldn't find any. There are "states", states can "accept" or "reject". There are "transitions" and "actions", but there seems to be no commonly agreed term for a general action of transitioning. The descriptive name perhaps would be I guess |
Done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caught some minor naming nitpicks, other than that the implementation looks really solid. Nice work!
lib/apps.fnl
Outdated
(fn [] | ||
(unbind-keys))))) | ||
|
||
(fn my-effect-handler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor change but could use a better name. Some options that come to mind:
- app-effect-handler
- map-effect-handler
- named-effect-handler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep! I forgot about this one
lib/apps.fnl
Outdated
|
||
(fn proxy-actions | ||
[fsm] | ||
(fn action-watcher |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we discussed naming functions after verbs. Though this is pretty concise now maybe it would benefit from being an inline function?
lib/modal.fnl
Outdated
@@ -54,7 +54,7 @@ switching menus in one place which is then powered by config.fnl. | |||
nil)))) | |||
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
;; Event Dispatchers | |||
;; Action senders |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps there's a better phrase that suggests "Here's some public API functions you can call whenever"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't export these but I can name this heading better.
_action (atom.new nil) | ||
_effect (atom.new nil) | ||
_extra (atom.new nil)] | ||
(fsm.subscribe (fn [{: prev-state : next-state : action : effect : extra}] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reminds me to make an it-async
that takes a callback function to call after the tests are performed. Then instead of all these atoms we can perform the tests in the subscribe callback itself.
We could try performing those tests in the callback, it might work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
This reworks the statemachine as imagined by @eccentric-j.
It keeps the state machine static, only uses 2 atoms: 1 for current state and one for context.
Each state defines a transition function for each action it supports. These functions return a new state, a new context, and an effect. Effects are sent to all subscribers, along with the new state and new context. They cannot modify the state or context, but can instead use it. The intent here is to allow these 'effect handlers' to display modals, set up hot keys, etc.
Additionally, we add a helper
effect-handler
, which is a higher order function that takes a map of effect->handler, and closes over an atom. The handlers provided in this way should return their own cleanup function, which is stored in the atom. This allows the returned function to be registered as an effect handler and to have the returned cleanup function automatically called on the subsequent event.[ ] Add modal tests[ ] (Maybe?) Integrate new subscriber/stream