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
[Feature] Transient states/transitions #43
Comments
Will it remain in the transient state if none of the guards match? So the state is not simply a transient state, but rather an "immediate exit". I also have to point out that the order of evaluating guards is significant, so using an object might not be a good choice for this. Would this solution also be used to e.g. deal with guards? The same problem exists there. When I write a state and want to handle an event with a few guards, then the various guards need to be evaluated in the right order in order for the behaviour to be correct. Perhaps:
This could work for normal events too, right?
Only transition to foo if the contition holds, otherwise let the event be handled by parent states. |
The reason I chose objects is because:
The fourth point is the most important for me, and is the guiding principle for designing the API. We can't avoid non-determinism and uniqueness with arrays, but we can naturally with object/key pairs. |
This constraint causes the boolean logic strings / functions to become a lot more complicated than necessary. If I want to transition to X if foo, otherwise, transition to Y if bar, else transition to Z if not baz, else transition to X if somethingelse. That's four tests. I can write this using if tests:
However, if I'm constrained to encode the first and last conditions in the same if-test I have to write each of them as mutually exclusive boolean expressions (so that at most one evaluates to true):
I don't see how that's any better; it's impossible for me to read this boolean logic and know what's happening; and it's impossible to maintain, I don't even know how to write the logic for Y and Z without using venn diagrams.
The list of transitions that can be chosen from any given event in any particular state is in the order of magnitude 1 to 10, I think this qualifies as an premature optimization.
I think in the arrays vs objects perspective, both have this aspect.
It only introduces nondeterminism if you impose the constraint that any two states must only be joined by a single transition. Using an array leaves everything completely deterministic. The four if/else is completely deterministic, it's just a lot easier to write (and read). |
Okay yeah, I can see how that can easily get complex @mogsie. So we introduce this syntax instead (taking the first example): const updateMachine = Machine({
initial: 'G',
states: {
G: {
on: { UPDATE_BUTTON_CLICKED: 'E' },
},
E: {
on: {
// transient transition
'': [
{ target: 'D', cond: ({ data }) => !data }, // no data returned
{ target: 'B', cond: ({ status }) => status === 'Y' },
{ target: 'C', cond: ({ status }) => status === 'X' },
{ target: 'F' } // default, or just the string 'F'
]
}
},
D: {},
B: {},
C: {},
F: {}
}
}); I can see this working, and it does simplify the boolean logic. To @mogsie's point, it's easier to represent This array-based syntax for determining the next transition should also be allowed for other actions, as well. It doesn't interfere with the object-based syntax (and actually, I can see it replacing object-based syntax in a future version). Thanks for the insight, @mogsie. |
Best explained in Horrock's book:
Below is an example of a transient state, and how it can be useful:
Proposed API:
Instead of explicitly defining a "transient state", we allow any state to implicitly become transient by introducing transient transitions, which are checked immediately upon entering the state. This has the same semantics of transient states as described in the book. The transient transition (or "immediate transition") will be based on an empty event string, since that best demonstrates that it comes from no event:
UPDATED: see #43 (comment)
Actions will be evaluated in this order (using the above example):
onExit
for Gactions
for G -> E (ON_BUTTON_CLICKED)onEntry
for Eactions
for determined transient transition from E -> D (or B or C)onExit
for EonEntry
for determined next state (D or B or C)And a transition will evaluate to the ultimately determined state:
Thoughts? Feedback?
The text was updated successfully, but these errors were encountered: