0

Erlang の gen_fsm モジュールを使用してメニュー オプションを管理するかなり大きな USSD アプリケーションがあります。

menus_fsm.erl現在のバージョンには、 5000 行以上の gen_fsm 関連コードを含む単一のファイルがあります。menus_fsm.erl次のバージョンでは、個別のファイルに分割して、将来の保守を容易にする機会が与えられます。

古いバージョンでは、ヘルプ メニューを表示するには、次のようにします (help_menu/1メイン メニューを表示する図示されていないコードから呼び出されます)。

-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 へのエントリ ポイントなどを示す多くのコードを省略しました。

新しいバージョンでは、次のように、から呼び出される新しいモジュールにhelp_menu/1とを移動したいと考えています。waitHelpMenuChoice/2help_menumenus_fsm

-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期待されているため、開始した場所に戻ります。waitHelpMenuChoicemenus_fsm

問題のある行を次のように置き換えようとしました

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

しかし、それは次のようなエラーにつながるだけです: {badarg,[{erlang,apply,[conv_fsm,#Fun<help_menu.waitHelpMenuChoice.2>,[]]}

これを回避する方法について何か提案はありますか?

4

2 に答える 2

0

私は自分の質問に対する解決策を見つけることができました。これが明らかだと思われる場合は、私がErlangに少し慣れていないことが原因である可能性があります。

他のモジュールに代わって状態遷移を処理する新しい関数wait_for_menu_response/2をモジュールに追加しました。menus_fsm

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

次に、help_menuモジュールを次のように変更しました。

-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_fsmwait_for_menu_responsewait_for_menu_responsehelp_menu:waitHelpMenuChoice/2help_menu:waitHelpMenuChoice/2

実際、私の最終バージョンでは、関数が3番目のパラメーターとしてmenus_fsm:send_menu受け入れるように変更されたため、関数は単純に次のようになります。fun waitHelpMenuChoice/2help_menu

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

しかし、上記の私の説明は、アイデアをよりよく示していると思います。

于 2012-04-05T13:24:41.143 に答える
0

http://www.erlang.org/doc/man/gen_fsm.html#enter_loop-6を使用してそれを行うことができますか? 別の fsm 内で呼び出すことができるかどうかはわかりませんが、試してみる価値はあります。

于 2012-04-05T12:20:36.417 に答える