I'm wondering if it would be useful to provide a way to have guards be kept out of the state machine, to keep it all "pure function".
The way I thought it might work would be to add a parameter to the transition
to specify the value of any guards. The guards would always be optional, but would of course influence the outcome. Here's a machine with a named guard (I use 'guard' instead of 'cond' because I like statechart terminology better than scxml):
m = Machine({
foo: {
on: {
A: bar,
B: {
target: bar
guard: isEmpty
}
}
},
bar: {}
})
var object = []
direct = transition(m.initialState, 'A'); // transitions directly to bar, as before
guarded = transition(m.initialState, 'A'); // about to transition from foo to bar, but it was guarded.
guarded.missingGuards; // [ "isEmpty" ]
failure = transition(m.initialState, 'A', { isEmpty: false }); // state is still "foo" — the event was basically not handled.
success = transition(m.initialState, 'A', { isEmpty: true }); // state is "bar" as the guard allowed the transition to happen.
A successful state transition requires that you verify that missingGuards
is empty. If there are any missingGuards
then you need to retry the state transition providing those missing guards. The missingGuards
would be a property on the State object returned.
The third parameter to transition would be somewhat of a bitset with the names of the guards and their boolean values.
The guard
attribute should allow boolean logic, though, so that it's possible to say guard: "!isEmpty && ready"
in the machine definition, and that this would require the isEmpty
and ready
guards to be provided.
So, historically, some statechart implementations have the notion of a "junction" state, and I think we can introduce something like that. I say that because:
With the above, it's hard to represent multiple conditions. I think we can keep the existing syntax, with a couple changes:
cond
can be a string, just like actionscond: true
(or something similar?) can represent the "fallback" condition (sink state? not sure if those semantics apply here)And to support this, we'd introduce a
JunctionState
:The above is very much subject for discussion... maybe we can somehow represent the "default" state inside the
conditions
object, maybe we should rename theconditions
object, etc.What do you think?