Erlang プロセス Scheme アクタ

Erlangの根底にある、メッセージを送受しあうオブジェクトという考え方は、
SimulaやSmalltalk、そしてCarl Hewittのアクタモデルだ。

アクタモデルをもとに、SteeleとSussmanがSchemeを作った。

Scheme使いの私としては、Erlangは押さえておかねば。今更ながらに入門してみた。
(FUSEファイルシステムを作れるようになったから、次はプロセスだ、というのもある)

と、いうわけで、consセルをアクタならぬプロセスで作ってみた。この調子でいけば自然数もプロセスで作れる。

-module(cons).
-export([cons/2,atomp/1,car/1,cdr/1,list/1]).

rpc(Pid, Request) ->    
    Pid ! {self(), Request},
    receive
	{Pid, Response} ->
	    Response
    end.

% consアクタ
cons(X,Y) ->
    receive
	% atomp メッセージに false と返事する.
	{Cont, atomp} ->
	    Cont ! {self(),false},
	    cons(X,Y);
	% car メッセージに X と返事する.
	{Cont, car} ->
	    Cont ! {self(),X},
	    cons(X,Y);
	% cdr メッセージに Y と返事する. リストの場合は Y にプロセスIDが入っている.
	{Cont, cdr} ->
	    Cont ! {self(),Y},
	    cons(X,Y)
    end.

% アクタにメッセージを送る関数.
atomp(X) -> rpc(X, atomp).
car(X)   -> rpc(X, car).
cdr(X)   -> rpc(X, cdr).

% consアクタを連ねてリストを作る関数.
list([])    -> null;
list([X|Y]) -> spawn(fun() -> cons(X,list(Y)) end).
-module(test).
-import(cons,[cons/2,atomp/1,car/1,cdr/1,list/1]).
-export([test_cons/0,test_list/0]).

test_cons() -> 
    % consアクタを作る.
    Cons = spawn(fun() -> cons(hello, world) end),
    % consアクタにメッセージを送って返事をプリントする.
    io:format("~p ~p ~p~n", [atomp(Cons), car(Cons), cdr(Cons)]).

test_list() ->
    % consアクタを連ねてリストを作る.
    List = list([0,1,2]),
    io:format("~p ~p ~n", [        car(List),          cdr(List)]),
    io:format("~p ~p ~n", [    car(cdr(List)),     cdr(cdr(List))]),
    io:format("~p ~p ~n", [car(cdr(cdr(List))),cdr(cdr(cdr(List)))]).

実行。

Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0] [kernel-poll:false]

Eshell V5.5.5 (abort with ^G)
1> c(test).
{ok,test}
2> test:test_cons().
false hello world
ok
3> test:test_list().
0 <0.41.0>
1 <0.42.0>
2 null
ok

参考文献:SchemeとActor理論

プログラミングErlang

プログラミングErlang