Erlang 为什么gen_fsm状态方法必须返回某些内容?

Erlang 为什么gen_fsm状态方法必须返回某些内容?,erlang,otp,fsm,Erlang,Otp,Fsm,我目前正在阅读LYAE,我试图理解为什么必须gen_fsm状态方法必须根据 有人能解释一下我是否有3种状态方法:a、b和c,状态机的定义如下: a()-> receive something -> b(); _ -> error(err) end. b()-> receive somethingelse-> c(); _ -> end. 为什么我需要next state方法的返回结果 someMethod(

我目前正在阅读
LYAE
,我试图理解为什么必须
gen_fsm
状态方法必须根据

有人能解释一下我是否有3种状态方法:
a
b
c
,状态机的定义如下:

a()->
  receive
    something -> b();
    _ -> error(err)
  end.

b()->
  receive 
    somethingelse-> c();
    _ ->
  end.
为什么我需要next state方法的返回结果

someMethod()->
   receive 
      _ -> 
           {next_state, NextStateName, NewStateData}=someNextMethod(),
          //why would i place code here? What could i possibly do with the above tuple ?
   end.

我不明白为什么要在调用下一个状态方法后加上代码?所有调用都是递归的,因此除了fsm结束或抛出后我可以实际执行某些操作的初始状态之外,我为什么要将代码置于其他状态?

您是正确的,不需要返回值,并且您必须对某个函数进行递归调用,该函数将等待接收语句:这是使事情发展的必要条件(因为变量的不变性)并对新消息作出反应

重点是,您的示例是一个单模块状态机,而当您使用gen_fsm行为时,至少有两个模块在起作用:

  • 隐式和通用gen_fsm行为模块本身
  • 以及您正在编写的特定回调模块
每个模块都有非常不同的角色

  • 通用的一个负责保持状态并接收消息(这就是为什么您不能在代码中注意到这一点),它提供不同类型的消息:同步或异步,到一个状态或任何状态,通过gen_fsm接口或“自由发送”消息…它还管理操作模式:初始化、停止、代码更改…它还在后台管理与OTP系统的接口。由于它是一个通用模块,它无法知道您要定义的状态和转换
  • 回调模块由gen_fsm调用(几乎)每次收到消息时,调用的函数取决于状态和消息。回调模块负责定义状态机的状态和转换,并将返回值发送回gen_fsm。返回值包含多个字段,下一个状态是必需的,因为gen_fsm必须在要“进入”的状态-进入状态是一个图像,它只是存储在变量中并由主fsm循环维护的状态名称-它还可以维护更多信息(通常也称为状态信息,这会使人混淆,例如,对于门锁系统,当前的密码)。返回值还可能包含其他内容,如同步消息情况下对调用方的回复、下一条传入消息之前的超时、停止fsm的请求
简而言之,gen_fsm是一个简单的递归循环,等待“事件”至少维护State_name变量的消息。它使用存储在回调模块中的helper函数来描述其行为。与您所说的相去甚远,但有通用模块带来的约束,以及集成到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}
或:


我不确定我是否理解你的问题。但是,如果你使用的是
genu fsm
,你就不会自己调用
receive
gen\u fsm
的全部要点是你只实现你的应用程序逻辑,而不必每次都从头开始创建一个状态机。因此元组的要点是它告诉
gen_fsm
库下一步要做什么。作为补充说明,
gen_fsm
已被弃用,您应该使用
gen_statem
来代替。在本书中,似乎所有状态都是递归调用的,一个从另一个调用。我不明白在这种情况下,为什么在调用方方法中调用下一个状态后会有额外的逻辑。a所有这些例子都是在介绍
gen\u fsm
模块之前。它只是向您展示了状态机是什么。您是否研究过
gen\u server
?您可以自己实现一个通用服务器,就像一些OTP书籍所做的那样,以便向您展示一点关于OTP库的知识。但是,OTP书籍如何使用OTP gen_服务器行为,这使代码更加简单。在使用gen_服务器行为时,您定义的每个函数都必须返回一个元组,该元组指示OTP库下一步要做什么……类似地,LYSE向您展示了如何自己实现gen_fsm,例如cat_fsm、dog_fsm,但在使用OTP gen时_在fsm行为中,您定义的每个函数都必须返回一个元组,该元组指示OTP库下一步要做什么。如果查看(过于)复杂的交易示例,所有相关函数的最后一行都返回一个元组——元组后没有代码。
  {next_state, NextStateName, NewStateData}=someNextMethod(),
  {next_state, NextStateName, NewStateData + 1}
  {next_state, NextStateName, NewStateData}=someNextMethod(),
  ModifiedStateData = do_calculation(NewStateData),
  {next_state, NextStateName, ModifiedStateData}