2007/06/22

体重が52.7kg

危機的状況ではないだろうか?

2007/06/19

Erlang サンタクロース問題

サンタクロース問題
43行ではないけど、Erlang で。
なんだか random が怪しい?
after 0 でトナカイを優先しないといけなかったですね。


-module(santa).
-compile(export_all).

-record(stat, {'こびと'=[], 'トナカイ'=[]}).

start() ->
register('サンタ', spawn_link(?MODULE, 'サンタ', [#stat{}])),
lists:foreach(fun(N) -> spawn_link(?MODULE, 'こびと_init', [N]) end,
lists:seq(1, 10)),
lists:foreach(fun(N) -> spawn_link(?MODULE, 'トナカイ_init', [N]) end,
lists:seq(1, 9)).

'サンタ'(#stat{'トナカイ'=X}=Stat) when length(X) == 9 ->
'サンタ働く'("おもちゃくばり", X),
'サンタ寝てる'(Stat#stat{'トナカイ'=[]});
'サンタ'(#stat{'こびと'=X}=Stat) when length(X) == 3 ->
'サンタ働く'("おもちゃ会議", X),
'サンタ寝てる'(Stat#stat{'こびと'=[]});
'サンタ'(Stat) ->
'サンタ寝てる'(Stat).

'サンタ働く'(What, Who) ->
io:format("~s開始...", [What]),
sleep(10),
io:format("終了。~n"),
lists:foreach(fun(A) -> A ! 'おつかれさま。' end, Who).

'サンタ寝てる'(Stat) ->
receive
{'トナカイ', N, X} ->
io:format("トナカイ~bが来た。~n", [N]),
'サンタ'(Stat#stat{'トナカイ'=[X|Stat#stat.'トナカイ']})
after 0 ->
receive
{'こびと', N, X} ->
io:format("こびと~bが来た。~n", [N]),
'サンタ'(Stat#stat{'こびと'=[X|Stat#stat.'こびと']})
end
end.

'こびと_init'(N) ->
random:seed(N, N*N, N*N*N*N),
'こびと'(N).

'こびと'(N) ->
sleep(30),
'サンタ' ! {'こびと', N, self()},
receive
'おつかれさま。' ->
'こびと'(N)
end.

'トナカイ_init'(N) ->
random:seed(N*N*N, N*N*N, N),
'トナカイ'(N).
'トナカイ'(N) ->
sleep(30),
'サンタ' ! {'トナカイ', N, self()},
receive
'おつかれさま。' ->
'トナカイ'(N)
end.

sleep(N) ->
X = random:uniform(N),
timer:sleep(X*1000).

2007/06/18

Erlang オペレータと関数の壁

関数は fun my_module:my_fun/1 のような型で使えるが、オペレータはこれができない。
でも、Erlang ではシングルクウォートで囲めば任意の関数名(atom)を作れるので、次のように '+' とかいう関数を定義してみる。
すると、lists:foldl(fun ope:'+'/2, 0, lists:seq(1, 100)). みたいなことができるけど、嬉しいかなぁ?


-module(ope).
-export(['+'/2, '-'/2, '*'/2, '/'/2, test/0]).

'+'(A, B) ->
A + B.

'-'(A, B) ->
A - B.

'*'(A, B) ->
A * B.

'/'(A, B) ->
A / B.

test() ->
lists:foldl(fun ope:'+'/2, 0, lists:seq(1, 100)).

Erlang error_handler

定義されていない関数が呼ばれたときのハンドラです。
定義されていない関数が呼ばれた場合 error_handler:undefined_function/3 が呼ばれます。
error_handler:undefined_function/3 は呼ばれた関数のモジュールをロードし、ロードできればその関数をもう一度呼んでみる、とうような動きをします。

error_handler:undefined_function/3 をユーザ定義の関数で置き換えることができます。
マニュアルには危険なので要注意、とうようなことが書かれていますが、この機能でモジュールの継承のようなものができないでしょうか。


-module(my_module).
-compile(export_all).

undefined_function(my_module, Func, Args) ->
io:format("no sush funciton!! ~p:~p(~p)~n", [my_module, Func, Args]);
undefined_function(Module, Func, Args) ->
io:format("original handler...~n"),
error_handler:undefined_function(Module, Func, Args).

test() ->
process_flag(error_handler, my_module),
my_module:foo("Hello"),
xxxx:yyyy(zzzz).

2007/06/13

Erlang/OTP R11B-5 has been released

Erlang/OTP R11B-5 がリリースされました。
バイナリ内包表記はまだリリースされないみたいです。

2007/06/11

Erlang 文字列をコンパイルする

文字列をコンパイルする方法です。

erl_scan:tokens で1文ずつスキャン。
erl_parse:parse_form で1文ずつパース。
compile:forms でモジュール単位でコンパイル。
code:load_binary でコンパイルしたものをロードです。

改行コードは \n にしておかないとだめです。


-module(compile_string).
-export([compile/1, test/0]).

compile(FormsStr) ->
Forms = mk_forms(lists:flatten(FormsStr)),
{ok, M, B} = compile:forms(Forms),
{module, M} = code:load_binary(M, atom_to_list(M), B),
M.

mk_forms(String) ->
mk_forms(String, []).

mk_forms([], Acc) ->
lists:reverse(Acc);
mk_forms(S, Acc) ->
{done, {ok, Tokens, _Line}, Rest} = erl_scan:tokens([], S, 0),
{ok, Parsed} = erl_parse:parse_form(Tokens),
mk_forms(Rest, [Parsed|Acc]).

test() ->
S = "-module(fib).
-export([fib/1]).
fib(1) -> 1;
fib(2) -> 1;
fib(N) -> fib(N-1) + fib(N-2).
",
compile(S),
fib:fib(10). % コンパイルした関数を呼出す。

もっと簡単な方法があるような気がします。
Common Lisp ならマクロでおしまいですね。
正規表現を入力にコンパイルされた関数を返す、なんて使い方をしようかと思っています。

2007/06/08

体重が

53.7kg
もうちょっと食べないとまずいかな。

ちかごろうまくステップが踏めていない。
「躍りなせい」と、ばのーらの羊が言った。

Erlang で正規表現を実装して遊んでいる。
多少はかたちになった。