Erlang gen_fsmで作る鳴き続ける猫

  • 5
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

有限ステートマシンを簡単に実装できるOPTのgen_fsm ビヘイビア(behaviour)を利用して、鳴き続ける猫とたまに逃げる猫を実装してみました。

スクリーンショット 2016-06-15 12.06.41.png
スクリーンショット 2016-06-15 12.06.44.png

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. たまに逃げる猫

スクリーンショット 2016-06-15 12.06.44.png

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"
+++++++++++++