4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ErlangのGen_Fsm Behaviourを使った電卓

Posted at

Erlangの練習に、Gen_Fsm Behaviourを使って電卓を作ってみました。
Fsmは有限ステートマシンです。

数字ボタンと+ボタン、=ボタンがある電卓をイメージしています。number, plus, equalというイベントを定義し、numberイベントには数字データが付属します。
状態は、waitとwait2を定義しています。waitは一つ目のデータを入力中で、wait2は二つ目のデータを入力中であるという状態です。

gen_fsmでは、まずinitコールバックで初期状態を返します。フォーマットは{ok, 状態名, 状態データ}です。

init(Memory1) ->
    {ok, wait, {Memory1, []}}.

そして状態名を名前とする関数を作ります。イベントが送られた際に、現在状態と同じ名前の関数が呼ばれます。

wait({イベント, パラメータ}, 状態データ) ->
    ..いろいろな処理

このいろいろな処理の中で、次に遷移する状態を返します。

{next_state, 次の状態名, 状態データ}

イベントの送信にはsend_eventという関数があります。第1引数でfsmの名前を指定し、第2引数では{イベント名、パラメータ}を指定します。

gen_fsm:send_event(名前, {イベント, パラメータ}).

ソース

-module(cal).
-behaviour(gen_fsm).

-export([start_link/0, push_number/1, push_plus/0, push_equal/0]).
-export([init/1]).
-export([wait/2, wait2/2]).

start_link() ->
    gen_fsm:start_link({local, cal}, cal, [], []).

push_number(Digit) ->
    gen_fsm:send_event(cal, {number, Digit}).

push_plus() ->
    gen_fsm:send_event(cal, {plus, []}).

push_equal() ->
    gen_fsm:send_event(cal, {equal, []}).

init(Memory1) ->
    {ok, wait, {Memory1, []}}.

wait({Event, Digit}, {Memory1, Memory2}) ->
    case Event of
	number ->
		NewMemory = [Digit | Memory1],
	    io:format("~p~n", [lists:reverse(NewMemory)]),
	    {next_state, wait, {NewMemory, []}};
	plus ->
	    {next_state, wait2, {Memory1, Memory2}};
	equal ->
	    io:format("miss~n"),
	    {next_state, wait, {[], []}}
    end.

wait2({Event, Digit}, {Memory1, Memory2}) ->
    case Event of
	number ->
		NewMemory = [Digit | Memory2],
	    io:format("~p+~p~n", [lists:reverse(Memory1), lists:reverse(NewMemory)]),
	    {next_state, wait2, {Memory1, NewMemory}};
	plus ->
	    {next_state, wait2, {Memory1, Memory2}};
	equal ->
	    io:format("=~p~n",[ mem_to_num(Memory1) + mem_to_num(Memory2) ]),
	    {next_state, wait, {[], []}}
    end.

mem_to_num(M) ->
	{I, S} = lists:foldl(fun(X, {I, Sum}) -> {I * 10, X*I + Sum} end, {1, 0}, M),
	S.

実行結果

1> c(cal).
{ok,cal}
2> cal:start_link().
{ok,<0.39.0>}
3> cal:push_number(3).
[3]
ok
4> cal:push_number(8).
[3,8]
ok
5> cal:push_plus().   
ok
6> cal:push_number(2).
[3,8]+[2]
ok
7> cal:push_number(1).
[3,8]+[2,1]
ok
8> cal:push_equal().  
=59
ok
9> 
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?