向井さんのとこへのクエックさんのコメントに目から鱗が落ちた。
カンマは and で、セミコロンは or です。
カンマで区切られているものは全て実行されますが、セミコロンで区切られているものはそのいずれかが実行されます。ガードでもカンマは and で、セミコロンは or ですよね。
あー……こんなことやっとる場合じゃないんだが……すんごい逃避行動……
ということで、Erlang でπ計算を再現するモジュールを書いてみた。 えーと、まあ、ソースはこんな感じ。
% cat pi.erl
-module(pi).
-export([new/0,
send/2,
recv/2,
display/1,
replication/2,
replication/3]).
-define(REPL_NUM, 10).
channel(Queue) ->
receive
{get, Pid} when is_pid(Pid) ->
{Val, Rest} = case queue:out(Queue) of
{{value, V}, R} -> {V, R};
{empty, Q} ->
receive
{put, Msg} -> {Msg, Q}
end
end,
Pid ! {channel_response, Val},
channel(Rest);
{put, Msg} ->
channel(queue:in(Msg, Queue))
end.
new() -> spawn(fun() -> channel(queue:new()) end).
sendSeq(Channel, Msg) when is_pid(Channel) ->
Channel ! {put, Msg}.
send(Channel, Msg) ->
spawn(fun() -> sendSeq(Channel, Msg) end).
recvSeq(Channel) when is_pid(Channel) ->
Channel ! {get, self()},
receive
{channel_response, Val} -> Val
end.
recv(Channel, Fun) when is_function(Fun, 1) ->
spawn(fun() ->
V = recvSeq(Channel),
Fun(V)
end).
display(Channel) -> io:format("~p~n", [recvSeq(Channel)]).
replication(Channel, Fun) -> replication(?REPL_NUM, Channel, Fun).
replication(Num, Channel, Fun) when is_integer(Num),
is_pid(Channel),
is_function(Fun, 1) ->
lists:map(
fun(_) ->
spawn(fun() -> mk_repl_proc(Channel, Fun) end)
end,
lists:seq(1, Num)).
mk_repl_proc(Channel, Fun) ->
{Pid, Ref} = erlang:spawn_monitor(
fun() ->
V = recvSeq(Channel),
Fun(V)
end),
receive
{'DOWN', Ref, process, Pid, Reason} ->
case Reason of
normal -> mk_repl_proc(Channel, Fun);
ErrReason -> erlang:error(ErrReason)
end
end.
んで、こんな感じで書く。
Eshell V5.5.4 (abort with ^G)
1> c(pi).
{ok,pi}
2> X = pi:new().
<0.37.0>
3> pi:send(X, 123), pi:recv(X, fun(V) -> erlang:display(V) end).
123
<0.40.0>
4> C = pi:new().
<0.42.0>
5> pi:send(X,C), pi:recv(C,fun(V)->erlang:display(V)end), pi:recv(X,fun(D)->pi:send(D,"abc")end).
<0.46.0>
"abc"
例はπ-calculus 超入門から拝借。 あとはまあ、こんな感じ↓
6> f().
ok
7> Fact = pi:new().
<0.50.0>
8> pi:replication(Fact, fun({N,R}) ->
8> if N == 0 -> pi:send(R, 1);
8> true -> C = pi:new(),
8> pi:send(Fact, {N-1, C}),
8> pi:recv(C, fun(X) -> pi:send(R, N*X) end)
8> end
8> end).
[<0.52.0>,
(略)
<0.61.0>]
9> R = pi:new().
<0.73.0>
10> pi:send(Fact, {5, R}).
<0.75.0>
11> pi:display(R).
120
ok
12> pi:send(Fact, {10, R}).
<0.105.0>
13> pi:display(R).
3628800
ok
そこそこ遊べるんじゃないだろうか。 replication の辺りが手抜きで、用意したプロセスを消す方法を用意していなかったりするけど。
なかなか集中できなくて困っているときは静かなのに、やっとのことで集中し始めた頃に「あお〜ん」と一声。 せっかくの集中力は霧散。
なかなか眠れなくてうだうだしてるときは静かなのに、ようやくうとうとし始めた頃に「がお〜ん」と一声。 ばっちり目が覚める。
偶然では片付けたくないほど頻繁に、こういうことがある。 もうちょっと集中しきってからなら平気なのに。 もうちょっと眠りが深くなってからなら平気なのに。 どう考えてもタイミングが良すぎるのだ。 ここ以外に無い、ってタイミングで鳴くんだもの。
きっと何かあるんだよ、猫ってやつには。 なんかこう、人が出すα波とかを感じとって、それに反応するとかさ。