有限ステートマシンを簡単に実装できるOPTのgen_fsm ビヘイビア(behaviour)を利用して、鳴き続ける猫とたまに逃げる猫を実装してみました。
1. 鳴き続ける猫
neko.erl
-module(neko).
-author("hami").
-behaviour(gen_fsm).
%% API
-export([start_link/1, cat/2, action/0]).
-export([init/1]).
start_link(CatName) ->
gen_fsm:start_link({local, neko}, neko, CatName, []).
init(CatName) ->
{ok, cat, CatName}.
action() ->
gen_fsm:send_event(neko, []).
%% 猫本体
cat(FromAction, CatName) ->
%% 鳴く
print(string:concat(atom_to_list(CatName), ":< meow")),
%% 次の状態
{next_state, cat, CatName}.
%% printer
print(Message) -> io:format("E: ~p~n",[Message]).
main.erl
-module(main).
-author("hami").
%% API
-export([main/0]).
main() ->
%% 猫生成
neko:start_link(shiro),
%% アクションを実行
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action().
make.sh
# コンパイルと実行
echo "+++++++++++++"
erlc ./neko.erl
erlc ./main.erl
echo "+++++++++++++"
erl -noshell -s main main -s init stop
echo "+++++++++++++"
実行結果
+++++++++++++
E: "shiro:< meow"
E: "shiro:< meow"
E: "shiro:< meow"
E: "shiro:< meow"
E: "shiro:< meow"
E: "shiro:< meow"
+++++++++++++
2. たまに逃げる猫
neko.erl
-module(neko).
-author("hami").
-behaviour(gen_fsm).
%% API
-export([start_link/1, cat/2, action/0]).
-export([init/1]).
start_link(CatName) ->
gen_fsm:start_link({local, neko}, neko, CatName, []).
init(CatName) ->
{ok, cat, {CatName, sleep, 0}}.
action() ->
gen_fsm:send_event(neko, []).
%% 猫本体
cat(FromAction, {CatName, CatStatus, StrokeCount}) ->
case CatStatus of
sleep ->
%% 鳴く
print(string:concat(atom_to_list(CatName), ":< meow")),
%% 次の状態
if StrokeCount + 1 < 3 ->
{next_state, cat, {CatName, sleep, StrokeCount + 1}};
StrokeCount + 1 >= 3 ->
{next_state, cat, {CatName, standing, 0}}
end;
standing ->
%% 逃げる
print(string:concat(atom_to_list(CatName), " ran away...")),
%% 次の状態
if StrokeCount + 1 < 3 ->
{next_state, cat, {CatName, standing, StrokeCount + 1}};
StrokeCount + 1 >= 3 ->
{next_state, cat, {CatName, sleep, 0}}
end;
_ ->
null
end.
%% printer
print(Message) -> io:format("E: ~p~n",[Message]).
main.erl
-module(main).
-author("hami").
%% API
-export([main/0]).
main() ->
%% 猫生成
neko:start_link(kuro),
%% アクションを実行
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action(),
neko:action().
make.sh
# コンパイルと実行
echo "+++++++++++++"
erlc ./neko.erl
erlc ./main.erl
echo "+++++++++++++"
erl -noshell -s main main -s init stop
echo "+++++++++++++"
実行結果
+++++++++++++
E: "kuro:< meow"
E: "kuro:< meow"
E: "kuro:< meow"
E: "kuro ran away..."
E: "kuro ran away..."
E: "kuro ran away..."
E: "kuro:< meow"
E: "kuro:< meow"
E: "kuro:< meow"
E: "kuro ran away..."
E: "kuro ran away..."
E: "kuro ran away..."
E: "kuro:< meow"
+++++++++++++