トップ «前の日記(2007-05-23) 最新 次の日記(2007-05-25)» 編集

じじぃの日記、ツッコミ可

初心者が書いた OCaml 入門
Spotlight tips サイト内リンク集
1970|01|02|
2003|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|

2007-05-24 [長年日記]

% [Erlang] なんという単純かつ明快なルール

向井さんのとこへのクエックさんのコメントに目から鱗が落ちた。

カンマは and で、セミコロンは or です。

カンマで区切られているものは全て実行されますが、セミコロンで区切られているものはそのいずれかが実行されます。ガードでもカンマは and で、セミコロンは or ですよね。

% [Erlang] Erlang でπ計算

あー……こんなことやっとる場合じゃないんだが……すんごい逃避行動……

ということで、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 の辺りが手抜きで、用意したプロセスを消す方法を用意していなかったりするけど。

% [雑談] 猫にはある種の超能力があるのではないかと、本気で思うことがある

なかなか集中できなくて困っているときは静かなのに、やっとのことで集中し始めた頃に「あお〜ん」と一声。 せっかくの集中力は霧散。

なかなか眠れなくてうだうだしてるときは静かなのに、ようやくうとうとし始めた頃に「がお〜ん」と一声。 ばっちり目が覚める。

偶然では片付けたくないほど頻繁に、こういうことがある。 もうちょっと集中しきってからなら平気なのに。 もうちょっと眠りが深くなってからなら平気なのに。 どう考えてもタイミングが良すぎるのだ。 ここ以外に無い、ってタイミングで鳴くんだもの。

きっと何かあるんだよ、猫ってやつには。 なんかこう、人が出すα波とかを感じとって、それに反応するとかさ。

お名前:
E-mail:
コメント:

トップ «前の日記(2007-05-23) 最新 次の日記(2007-05-25)» 編集

日記ってのは本来、自分で読み返すためにあるもんだよなあ……
もしくは有名人になったら死後に本になったりとかか?

RSS はこちら

jijixi at azito.com