在 Erlang 中不能 运行 fsm
Can not run fsm in Erlang
你好,我正在尝试 运行 fsm
在与 caller.I 不同的进程中使用 gen_statem
我还试图将调用者保留在其状态参数中,因此它可以在每次状态更改后更新。
我不断收到此错误:
** State machine <0.123.0> terminating
** Last event = {internal,init_state}
** When server state = {sitting_home,{state,"None",0,0,[<0.116.0>]}}
** Reason for termination = error:{'function not exported',
{fsm,callback_mode,0}}
** Callback mode = undefined
** Stacktrace =
** [{gen_statem,call_callback_mode,1,[{file,"gen_statem.erl"},{line,1610}]},
{gen_statem,enter,7,[{file,"gen_statem.erl"},{line,679}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]
=CRASH REPORT==== 12-Dec-2019::00:14:42.717000 ===
crasher:
initial call: fsm:init/1
pid: <0.123.0>
registered_name: []
exception error: undefined function fsm:callback_mode/0
in function gen_statem:call_callback_mode/1 (gen_statem.erl, line 1610)
in call from gen_statem:enter/7 (gen_statem.erl, line 679)
ancestors: [<0.116.0>]
message_queue_len: 0
messages: []
links: []
dictionary: []
trap_exit: false
status: running
heap_size: 1598
stack_size: 27
reductions: 5805
neighbours:
我查看了 erlang 文档,没有看到需要实现的回调 mode
here。
模块
-module(fsm).
-record(state,{
current="None",
intvCount=0,
jobCount=0,
monitor
}).
-export([init/1,start/0]).
-export([hire/2,fire/1,interview/2]).
-behaviour(gen_statem).
start()->
gen_statem:start(?MODULE,[self()],[]).
init(Monitor)->
{ok,sitting_home,#state{current="None",jobCount=0,intvCount=0,monitor=Monitor}}.
sitting_home({intv,Company},State=#state{intvCount=C,monitor=M})->
gen_statem:reply(M,"Got an interview from:"++Company++" going interviewing"),
{next_state,interviewing,State#state{intvCount=C+1}};
sitting_home(Event,State)->
gen_statem:reply(State#state.monitor,{unexpected , Event}),
{next_state,sitting_home,State}.
interviewing({rejected,Company},State)->
gen_statem:reply("Booh got rejected by :"++ Company),
{next_state,sitting_home,State};
interviewing({accepted,Company},State=#state{jobCount=J})->
gen_statem:reply("Hooray got accepted"),
{next_state,working,State#state{jobCount=J+1,current=Company}};
interviewing(_,State)->
gen_statem:reply("Unknown message"),
{next_state,interviewing,State}.
working(fire,State=#state{current=C})->
gen_statem:reply("Unexpected event"),
{next_state,working,State#state{current="None"}};
working(Event,State)->
gen_statem:reply("Unexpected event"),
{next_state,working,State}.
事件
hire(Company,PID)->
gen_statem:sync_send_event(PID,{hire,self(),Company},0).
fire(PID)->
gen_statem:sync_send_event(PID,{fire,self()},0).
interview(Company,PID)->
gen_state:sync_send_event(PID,{intv,Company},0).
P.S 我用 gen_statem
因为 shell 告诉我 gen_fsm
是 deprecated.I 不要知道 sync_send_event
的等价物。这可能是问题所在吗?
Module:callback_mode
is documented 在您链接的页面上。当每个状态(sitting_home
、interviewing
等)都有一个函数时,它应该是
callback_mode() -> state_functions.
状态函数采用 3 个参数,而不是 2 个。您缺少第一个参数,EventType
,应该是 {call, From}
在你的情况下。
sync_send_event
的等价物可以是 call
,但是你的状态函数应该总是回复。
您可以在回调的 return 值中组合 reply
和 next_state
,例如
working(Event,State)->
gen_statem:reply("Unexpected event"),
{next_state,working,State}.
可以变成
working({call, From}, Event, State)->
{next_state, working, State, {reply, From, "Unexpected event"}}.
即使你不这样做,reply
needs a From
argument:
working({call, From}, Event, State)->
gen_statem:reply(From, "Unexpected event"),
{next_state,working,State}.
你好,我正在尝试 运行 fsm
在与 caller.I 不同的进程中使用 gen_statem
我还试图将调用者保留在其状态参数中,因此它可以在每次状态更改后更新。
我不断收到此错误:
** State machine <0.123.0> terminating
** Last event = {internal,init_state}
** When server state = {sitting_home,{state,"None",0,0,[<0.116.0>]}}
** Reason for termination = error:{'function not exported',
{fsm,callback_mode,0}}
** Callback mode = undefined
** Stacktrace =
** [{gen_statem,call_callback_mode,1,[{file,"gen_statem.erl"},{line,1610}]},
{gen_statem,enter,7,[{file,"gen_statem.erl"},{line,679}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]
=CRASH REPORT==== 12-Dec-2019::00:14:42.717000 ===
crasher:
initial call: fsm:init/1
pid: <0.123.0>
registered_name: []
exception error: undefined function fsm:callback_mode/0
in function gen_statem:call_callback_mode/1 (gen_statem.erl, line 1610)
in call from gen_statem:enter/7 (gen_statem.erl, line 679)
ancestors: [<0.116.0>]
message_queue_len: 0
messages: []
links: []
dictionary: []
trap_exit: false
status: running
heap_size: 1598
stack_size: 27
reductions: 5805
neighbours:
我查看了 erlang 文档,没有看到需要实现的回调 mode
here。
模块
-module(fsm).
-record(state,{
current="None",
intvCount=0,
jobCount=0,
monitor
}).
-export([init/1,start/0]).
-export([hire/2,fire/1,interview/2]).
-behaviour(gen_statem).
start()->
gen_statem:start(?MODULE,[self()],[]).
init(Monitor)->
{ok,sitting_home,#state{current="None",jobCount=0,intvCount=0,monitor=Monitor}}.
sitting_home({intv,Company},State=#state{intvCount=C,monitor=M})->
gen_statem:reply(M,"Got an interview from:"++Company++" going interviewing"),
{next_state,interviewing,State#state{intvCount=C+1}};
sitting_home(Event,State)->
gen_statem:reply(State#state.monitor,{unexpected , Event}),
{next_state,sitting_home,State}.
interviewing({rejected,Company},State)->
gen_statem:reply("Booh got rejected by :"++ Company),
{next_state,sitting_home,State};
interviewing({accepted,Company},State=#state{jobCount=J})->
gen_statem:reply("Hooray got accepted"),
{next_state,working,State#state{jobCount=J+1,current=Company}};
interviewing(_,State)->
gen_statem:reply("Unknown message"),
{next_state,interviewing,State}.
working(fire,State=#state{current=C})->
gen_statem:reply("Unexpected event"),
{next_state,working,State#state{current="None"}};
working(Event,State)->
gen_statem:reply("Unexpected event"),
{next_state,working,State}.
事件
hire(Company,PID)->
gen_statem:sync_send_event(PID,{hire,self(),Company},0).
fire(PID)->
gen_statem:sync_send_event(PID,{fire,self()},0).
interview(Company,PID)->
gen_state:sync_send_event(PID,{intv,Company},0).
P.S 我用 gen_statem
因为 shell 告诉我 gen_fsm
是 deprecated.I 不要知道 sync_send_event
的等价物。这可能是问题所在吗?
Module:callback_mode
is documented 在您链接的页面上。当每个状态(sitting_home
、interviewing
等)都有一个函数时,它应该是callback_mode() -> state_functions.
状态函数采用 3 个参数,而不是 2 个。您缺少第一个参数,
EventType
,应该是{call, From}
在你的情况下。sync_send_event
的等价物可以是call
,但是你的状态函数应该总是回复。您可以在回调的 return 值中组合
reply
和next_state
,例如working(Event,State)-> gen_statem:reply("Unexpected event"), {next_state,working,State}.
可以变成
working({call, From}, Event, State)-> {next_state, working, State, {reply, From, "Unexpected event"}}.
即使你不这样做,
reply
needs aFrom
argument:working({call, From}, Event, State)-> gen_statem:reply(From, "Unexpected event"), {next_state,working,State}.