本文介绍了将gen_fsm状态更改为其他模块中的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个相当大的USSD应用程序,它使用Erlang的gen_fsm模块来管理菜单选项。

We have a fairly large USSD application that uses Erlang's gen_fsm module to manage the menu options.

当前版本只有一个 menus_fsm。包含5000多个gen_fsm相关代码的erl 文件。我们的下一个版本使我们有机会将 menus_fsm.erl 拆分为单独的文件,以使其将来更易于维护。

The current version has a single menus_fsm.erl file that contains 5000+ lines gen_fsm related code. Our next version gives us an opportunity to split menus_fsm.erl into separate files to make it more maintainable in the future.

在旧版本中,要显示帮助菜单,我们需要执行以下操作(从显示主菜单的未显示代码中调用 help_menu / 1 ):

In the old version, to display the help menu we do the following (help_menu/1 gets called from code not shown that displays the main menu):

-module(menus_fsm).
% Snipped some irrelvant code

help_menu(StateData) ->
    % Display the first menu
    send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
    {next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};

waitHelpMenuChoice(Params, StateData) ->
    io:format("Got Help menu response: ~p", [Params]),
    doTerminate(ok,"Help Menu", StateData).

我遗漏了很多显示FSM入口点的代码,依此类推。

I've left out a lot of code that shows the entry point into the FSM and so on.

在新版本中,我们希望移动 help_menu / 1 waitHelpMenuChoice / 2 到新模块 help_menu ,该模块从 menus_fsm 调用,如下所示:

In the new version, we'd want to move help_menu/1 and waitHelpMenuChoice/2 to a new module help_menu, which gets called from menus_fsm, like so:

-module( help_menu ).
% Snipped some irrelevant code

help_menu(StateData) ->
    menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
    {next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};

waitHelpMenuChoice(Params, StateData) ->
    io:format("Got Help menu response: ~p", [Params]),
    menus_fsm:doTerminate(ok,"Help Menu", StateData).

问题出在行 {next_state,waitHelpMenuChoice,StateData,?MENU_TOUT }; gen_fsm 期望 waitHelpMenuChoice 在模块 menus_fsm ,这使我回到了开始的地方。

The problem is with the line {next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};: gen_fsm expects the waitHelpMenuChoice to be in the module menus_fsm which takes me back to where we started.

我尝试用$ p $替换有问题的行b

I've tried to replace the problematic line with

{next_state, fun help_menu:waitHelpMenuChoice/2, StateData, ?MENU_TOUT};

但这只会导致如下错误:
{badarg,[{erlang,apply,[conv_fsm,#Fun< help_menu.waitHelpMenuChoice.2>,[]]}

but that just leas to an error like the following:{badarg,[{erlang,apply,[conv_fsm,#Fun<help_menu.waitHelpMenuChoice.2>,[]]}

有人对如何解决这个问题有什么建议?

Does anyone have any suggestions of how to get around this?

推荐答案

我设法找到了自己的问题的解决方案。如果这似乎很明显,那可能是因为我对Erlang有点陌生。

I managed to find a solution to my own question. If this seems obvious, it could be because I'm a bit new to Erlang.

我添加了一个新函数 wait_for_menu_response / 2 到模块 menus_fsm 代表其他模块处理状态转换。

I added a new function wait_for_menu_response/2 to module menus_fsm that handles state transitions on behalf of the other modules.

-module(menus_fsm),
-export([wait_for_menu_response/2]).
% ...snip...
wait_for_menu_response(Params, {Function, StateData}) ->
    Function(Params, StateData).

然后 help_menu 模块进行了如下更改:

Then the help_menu module was changed as follows:

-module( help_menu ).
% ...snip...

help_menu(StateData) ->
    menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
    {next_state, wait_for_menu_response, {fun waitHelpMenuChoice/2, StateData}, ?MENU_TOUT}.

waitHelpMenuChoice(Params, StateData) ->
    io:format("Got Help menu response: ~p", [Params]),
    menus_fsm:doTerminate(ok,"Help Menu", StateData).

所以 gen_fsm 保持在 menus_fsm 模块在调用 wait_for_menu_response 时,但是 wait_for_menu_response 现在可以自由调用 help_menu:waitHelpMenuChoice / 2 help_menu:waitHelpMenuChoice / 2 不需要进行任何修改。

so gen_fsm stays within the menus_fsm module when it invokes wait_for_menu_response, but wait_for_menu_response is now free to invoke help_menu:waitHelpMenuChoice/2. help_menu:waitHelpMenuChoice/2 did not need to be modified in any way.

实际上,在我的最终版本中, menus_fsm:send_menu 函数被修改为接受 fun waitHelpMenuChoice / 2 作为其第三个参数,因此 help_menu 函数简单地变为:

Actually, in my final version, the menus_fsm:send_menu function was modified to accept the fun waitHelpMenuChoice/2 as its third parameter, so that the help_menu function simply becomes:

help_menu(StateData) ->
    menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2",
        fun waitHelpMenuChoice/2).

但我认为以上解释更好地说明了这一点。

but I think my explanation above illustrates the idea better.

这篇关于将gen_fsm状态更改为其他模块中的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 01:08