Closed dkumsh closed 2 weeks ago
I'm also confused how the wild-card transition will avoid generating transitions for previously-defined wildcard states.
This actually works out of the box. I did not do anything for this, as it is covered by the wildcard transitions support, which had already been there. I only extended support to allow internal transitions
including in the wildcard context. Under the hood this only means that when target state is not explicitly specified, it is assumed to be an internal transition
and in that case the input state becomes the target state.
For example in test_wildcard_states_and_internal_transitions() :
statemachine! {
transitions: {
*State1 + Event2 = State2,
State2 + Event3 = State3,
_ + Event1 / increment_count, // Internal transition (implicit: omitting target state)
_ + Event3 / increment_count = _ , // Internal transition (explicit: using _ as target state)
},
derive_states: [Debug, Clone, Copy]
}
The macro generates the following transitions for processing Event3:
State2 + Event3 = State3,
State1 + Event3 / increment_count = State1,
State3 + Event3 / increment_count = State3,
And it is validated by the test, that Event3 in State2 does not increment the count (current state is State2, and the count is 1 before the following assertion is invoked):
assert_transition!(sm, Events::Event3, States::State3, 1);
while the same Event3 in State3, does increment
assert_transition!(sm, Events::Event3, States::State3, 3);
I pushed the fixes.
Hi @ryan-summers , would you approve this PR or we have anything undecided ?
Hi @ryan-summers,
I have rebased due to a merge conflict. I noticed that a new callback, transition_callback, had been added. Now, the transition logic looks as follows, and I am wondering about the purpose of having two different callbacks at practically the same point, transition_callback
and on_entry
. Should we consider using just one?
#on_exit
#action_code
let out_state = #states_type_name::#out_state;
self.context.log_state_change(&out_state);
self.context().transition_callback(&self.state, &out_state); // transition_callback
self.state = out_state;
#on_entry // on_entry callback
Hi @ryan-summers,
I have rebased due to a merge conflict. I noticed that a new callback, transition_callback, had been added. Now, the transition logic looks as follows, and I am wondering about the purpose of having two different callbacks at practically the same point,
transition_callback
andon_entry
. Should we consider using just one?#on_exit #action_code let out_state = #states_type_name::#out_state; self.context.log_state_change(&out_state); self.context().transition_callback(&self.state, &out_state); // transition_callback self.state = out_state; #on_entry // on_entry callback
The purpose of the transition_callback
is that its called on all transitions, where on_entry
is a unique function per entry state. That being said, there does feel like some redundancy here, specifically around log_state_change
. Maybe we can simply update log_state_change
to be replaced by transition_callback
.
The purpose of the
transition_callback
is that its called on all transitions, whereon_entry
is a unique function per entry state. That being said, there does feel like some redundancy here, specifically aroundlog_state_change
. Maybe we can simply updatelog_state_change
to be replaced bytransition_callback
.
Okay, I'll leave it to you to decide what to do with this as this is not part of this PR.
Thanks
Thanks for the PR and patience in getting this merged while I was traveling :)
This PR
Ident
with trailing space, breaking IDE rendering the macro (the fix trims the string before converting it toIdent
)The DSL supports internal transitions. Internals transition allow to accept some event and process an action and then stay in the current state. Internal transitions can be specified implicitly, e.g.
and now, after this change, can be specified explicitly, using underscore ('_')
or implicitly, by omitting the target state including symbol '='.
It is also possible to define wildcard implicit (or explicit using '_') internal transitions.
The example above demonstrates, how you could make Event2 acceptable in any state, not covered by any of the previous transitions, and to do an action to process it.
It is equivalent to:
See also
examples/wildcard_states_and_internal_transitions.rs
orexamples/internal_transitions_with_data.rs
for a usage example.