为什么 gen_fsm 状态方法必须 return 某些东西?
Why do gen_fsm state methods must return something?
我目前正在阅读 LYAE
并且我正在尝试理解为什么 gen_fsm
状态方法必须 return 根据 source
{reply, Reply, NextStateName, NewStateData}
{reply, Reply, NextStateName, NewStateData, Timeout}
{reply, Reply, NextStateName, NewStateData, hibernate}
{next_state, NextStateName, NewStateData}
{next_state, NextStateName, NewStateData, Timeout}
{next_state, NextStateName, NewStateData, hibernate}
{stop, Reason, Reply, NewStateData}
{stop, Reason, NewStateData}
如果我有 3 种状态方法:a
、b
和 c
,谁能给我解释一下,状态机定义如下:
a()->
receive
something -> b();
_ -> error(err)
end.
b()->
receive
somethingelse-> c();
_ ->
end.
为什么我需要下一个状态方法的 return 结果?
someMethod()->
receive
_ ->
{next_state, NextStateName, NewStateData}=someNextMethod(),
//why would i place code here? What could i possibly do with the above tuple ?
end.
我不明白为什么我要把代码放在之后调用下一个状态方法?所有调用都是递归的,所以除了在 fsm 结束或抛出后我可以实际做一些事情的初始状态之外,为什么我要把代码放在其他状态?
你是对的,不需要 return 值,你必须对某个函数进行递归调用,该函数将等待接收语句:有必要让事情发展(因为不变性变量)并对新消息做出反应。
重点是您的示例是一个模块状态机,而当您使用 gen_fsm 行为时,至少有 2 个模块在起作用:
- 隐式和通用 gen_fsm 行为模块本身
- 以及您正在编写的具体回调模块。
每个模块的作用非常不同。
- 通用的负责保持状态和接收消息(这就是为什么你不能在你的代码中处理这个),它提供不同类型的消息:同步或异步,一种状态或任何状态,通过 gen_fsm 接口或 "freely sent" 消息...它还管理操作模式:初始化、停止、代码更改...它还在后台管理与 OTP 系统的接口。由于它是一个通用模块,它无法识别您要定义的状态和转换。
- gen_fsm(几乎)每次收到消息时都会调用回调模块。调用的函数取决于状态和消息。回调模块负责为状态机定义状态和转换,它是通过将 return 值发送回 gen_fsm 来完成的。 return 值包含几个字段,下一个状态是强制性的,因为 gen_fsm 必须知道要进入哪个状态 "go" - 进入状态是图像,它只是存储的状态名称在一个变量中并由主 fsm 循环维护——它还可以维护更多信息(通常也称为状态信息,这是令人困惑的,例如门锁系统的当前密码)。 return 值还可能包含其他内容,例如在同步消息的情况下对调用者的回复、下一条传入消息之前的超时、停止 fsm 的请求...
简而言之,gen_fsm 是一个简单的递归循环,等待 "event" 消息,至少维护 State_name 变量。它使用存储在回调模块中的辅助函数来描述其行为。与您所说的相差无几,但具有通用模块带来的限制 - 以及集成到 OTP 和经过验证的代码的优势。
{next_state, NextStateName, NewStateData}=someNextMethod(),
//why would i place code here? What could i possibly do with the above tuple ?
例如:
{next_state, NextStateName, NewStateData}=someNextMethod(),
{next_state, NextStateName, NewStateData + 1}
或者:
{next_state, NextStateName, NewStateData}=someNextMethod(),
ModifiedStateData = do_calculation(NewStateData),
{next_state, NextStateName, ModifiedStateData}
我目前正在阅读 LYAE
并且我正在尝试理解为什么 gen_fsm
状态方法必须 return 根据 source
{reply, Reply, NextStateName, NewStateData}
{reply, Reply, NextStateName, NewStateData, Timeout}
{reply, Reply, NextStateName, NewStateData, hibernate}
{next_state, NextStateName, NewStateData}
{next_state, NextStateName, NewStateData, Timeout}
{next_state, NextStateName, NewStateData, hibernate}
{stop, Reason, Reply, NewStateData}
{stop, Reason, NewStateData}
如果我有 3 种状态方法:a
、b
和 c
,谁能给我解释一下,状态机定义如下:
a()->
receive
something -> b();
_ -> error(err)
end.
b()->
receive
somethingelse-> c();
_ ->
end.
为什么我需要下一个状态方法的 return 结果?
someMethod()->
receive
_ ->
{next_state, NextStateName, NewStateData}=someNextMethod(),
//why would i place code here? What could i possibly do with the above tuple ?
end.
我不明白为什么我要把代码放在之后调用下一个状态方法?所有调用都是递归的,所以除了在 fsm 结束或抛出后我可以实际做一些事情的初始状态之外,为什么我要把代码放在其他状态?
你是对的,不需要 return 值,你必须对某个函数进行递归调用,该函数将等待接收语句:有必要让事情发展(因为不变性变量)并对新消息做出反应。
重点是您的示例是一个模块状态机,而当您使用 gen_fsm 行为时,至少有 2 个模块在起作用:
- 隐式和通用 gen_fsm 行为模块本身
- 以及您正在编写的具体回调模块。
每个模块的作用非常不同。
- 通用的负责保持状态和接收消息(这就是为什么你不能在你的代码中处理这个),它提供不同类型的消息:同步或异步,一种状态或任何状态,通过 gen_fsm 接口或 "freely sent" 消息...它还管理操作模式:初始化、停止、代码更改...它还在后台管理与 OTP 系统的接口。由于它是一个通用模块,它无法识别您要定义的状态和转换。
- gen_fsm(几乎)每次收到消息时都会调用回调模块。调用的函数取决于状态和消息。回调模块负责为状态机定义状态和转换,它是通过将 return 值发送回 gen_fsm 来完成的。 return 值包含几个字段,下一个状态是强制性的,因为 gen_fsm 必须知道要进入哪个状态 "go" - 进入状态是图像,它只是存储的状态名称在一个变量中并由主 fsm 循环维护——它还可以维护更多信息(通常也称为状态信息,这是令人困惑的,例如门锁系统的当前密码)。 return 值还可能包含其他内容,例如在同步消息的情况下对调用者的回复、下一条传入消息之前的超时、停止 fsm 的请求...
简而言之,gen_fsm 是一个简单的递归循环,等待 "event" 消息,至少维护 State_name 变量。它使用存储在回调模块中的辅助函数来描述其行为。与您所说的相差无几,但具有通用模块带来的限制 - 以及集成到 OTP 和经过验证的代码的优势。
{next_state, NextStateName, NewStateData}=someNextMethod(),
//why would i place code here? What could i possibly do with the above tuple ?
例如:
{next_state, NextStateName, NewStateData}=someNextMethod(),
{next_state, NextStateName, NewStateData + 1}
或者:
{next_state, NextStateName, NewStateData}=someNextMethod(),
ModifiedStateData = do_calculation(NewStateData),
{next_state, NextStateName, ModifiedStateData}