[erlang-questions] gen_statem state enter call and changing t oanother state
Frans Schneider
fchschneider@REDACTED
Mon Jun 11 13:07:31 CEST 2018
Thanks Raimo,
See your point, but I am not yet really convinced.
Using a helper function would in my case.opinion make the code more
obliterative. I think the following code makes it very clear what goes
on while some helper function called from whatever other place would
make things much more obscure.
handle_event(enter,
_Old_state,
#state{reliability_level = reliable,
state1 = announcing} = State,
#data{changes = []} = Data) ->
{next_state, State#state{state1 = idle}, Data};
handle_event(enter,
_Old_state,
#state{reliability_level = reliable,
state1 = announcing},
#data{push_mode = true} = Data ->
{next_state, State#state{state1 = pushing}, Data};
handle_event(enter,
_Old_state,
#state{reliability_level = reliable,
state1 = announcing},
#data{push_mode = false,
heartbeat_period = Heartbeat_period} = Data) ->
Hb_timer_ref = erlang:start_timer(Heartbeat_period, self(), hb),
{keep_state, Data#data{heartbeat_timer_ref = Hb_timer_ref}};
Currently, I resort to testing for a particular condition in the state
enter code and insert a next event (changes_not_empty) to trigger the
state change I need, which however also introduces extra code and makes
things also less obvious.
Also, your co-locating argument is arguable since when using complex
states and handle_events, I tend to use a different ordering of the
functions, mostly focusing on the type of events to handle. (I know,
'enter' isn't an event of course.)
Frans
On 06/11/2018 10:45 AM, Raimo Niskanen wrote:
> On Mon, Jun 11, 2018 at 09:43:02AM +0200, Frans Schneider wrote:
>> Dear list,
>>
>> the state_enter_result(State) has as one its return values {next_state,
>> State, NewData, ...} but explicitly disallows the State to be different
>> from the current State, First, I find it confusing to allow
>> 'next_state' here since State cannot change but the name makes the
>
> Throughout gen_statem is is by design so that there is no difference
> between {next_state, SameState, NewData, ...}
> and {keep_state, NewData, ...}. It is {keep_state, ...} that is shorthand
> for {next_state, SameState, ...}.
>
> So dissalowing {next_state, ...} in a state_enter call would be an
> exception to the main rule that {next_state, ...} is the generic form.
>
> There might be situations where you have a helper function that calculates
> the next state so it would want to always return {next_state, ...}, and
> then you want to use it in a state_enter call context knowing it will
> always return {next_state, SameState, ...}. I think this use should be
> possible.
>
>> suggestion it can. Secondly, I would love to be able to actually make a
>> state change. Quite often i find myself running a few tests on entering
>> a state and making state changes based on these tests. Now I have to
>
> The state_enter call is intended for code to be executed when entering a
> state, making this code co-located in the source with the state's event
> handling code.
>
> If the state_enter call should be allowed to change states it would no
> longer be co-located since it would for example start a timer for the other
> state it changes to.
>
> The alternative to using state_enter calls would be to have a convention
> where you at exit from the other state go through a helper function
> that does what you need for state entry, and remember to use this
> function for every state entry to the state in question.
>
> I think your use case is a good example for when having a specialized state
> change function makes sense. There is no single state this kind of code
> clearly should be co-located with.
>
>> move these tests to all states which can have this state as a result and
>> go directly to the end state.
>>
>> Would it be possible to change state from a state enter call?
>
> I do not like that idea, for the reasons above...
>
>>
>> Frans
>
More information about the erlang-questions
mailing list