2006/12/25

Erlang OTP Design

OTP としましては。。。
Application(try_app.erl), Supervisor(try_sup.erl), Worker(try_srv.erl) とある。
Application を start すると Supervisor プロセスが起動する。
Supervisor は Worker プロセスを管理する。
Worker プロセスが仕事を行う。

3> lc([try_app, try_sup, try_srv]).
ok
4> application:start(try_app).
ok
5> gen_server:call(try_srv, 1).
{"Hello World!",1}
6> gen_server:call(try_srv, banobion).
{"Hello World!",banobion}


try_app.erl
%%%-------------------------------------------------------------------
%%% File : try_app.erl
%%% Author :
%%% Description : OTPのお試し
%%%
%%% Created : 25 Dec 2006 by
%%%-------------------------------------------------------------------
-module(try_app).

-behaviour(application).

%% Application callbacks
-export([start/2, stop/1]).

%%====================================================================
%% Application callbacks
%%====================================================================
%%--------------------------------------------------------------------
%% Function: start(Type, StartArgs) -> {ok, Pid} |
%% {ok, Pid, State} |
%% {error, Reason}
%% Description: This function is called whenever an application
%% is started using application:start/1,2, and should start the processes
%% of the application. If the application is structured according to the
%% OTP design principles as a supervision tree, this means starting the
%% top supervisor of the tree.
%%--------------------------------------------------------------------
start(_Type, StartArgs) ->
case try_sup:start_link(StartArgs) of
{ok, Pid} ->
{ok, Pid};
Error ->
Error
end.

%%--------------------------------------------------------------------
%% Function: stop(State) -> void()
%% Description: This function is called whenever an application
%% has stopped. It is intended to be the opposite of Module:start/2 and
%% should do any necessary cleaning up. The return value is ignored.
%%--------------------------------------------------------------------
stop(_State) ->
ok.

%%====================================================================
%% Internal functions
%%====================================================================


try_app.app
%% -*-erlang-*-
{application, try_app,
[{description, "OTP のお試し"},
{vsn, "0.1"},
{modules, [try_app, try_sup, try_srv]},
{registered, [try_app]},
{applications, [kernel, stdlib]},
{mod, {try_app,[]}}
]}.


try_sup.erl
%%%-------------------------------------------------------------------
%%% File : try_sup.erl
%%% Author :
%%% Description : OTP のお試し
%%%
%%% Created : 25 Dec 2006 by
%%%-------------------------------------------------------------------
-module(try_sup).

-behaviour(supervisor).

%% API
-export([start_link/1]).

%% Supervisor callbacks
-export([init/1]).

-define(SERVER, ?MODULE).

%%====================================================================
%% API functions
%%====================================================================
%%--------------------------------------------------------------------
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the supervisor
%%--------------------------------------------------------------------
start_link(_StartArgs) ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).

%%====================================================================
%% Supervisor callbacks
%%====================================================================
%%--------------------------------------------------------------------
%% Func: init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
%% ignore |
%% {error, Reason}
%% Description: Whenever a supervisor is started using
%% supervisor:start_link/[2,3], this function is called by the new process
%% to find out about restart strategy, maximum restart frequency and child
%% specifications.
%%--------------------------------------------------------------------
init([]) ->
AChild = {try_srv,{try_srv,start_link,[]},
permanent,2000,worker,[try_srv]},
{ok,{{one_for_all,0,1}, [AChild]}}.

%%====================================================================
%% Internal functions
%%====================================================================


try_srv.erl
%%%-------------------------------------------------------------------
%%% File : try_srv.erl
%%% Author :
%%% Description : OTP のお試し
%%%
%%% Created : 25 Dec 2006 by
%%%-------------------------------------------------------------------
-module(try_srv).

-behaviour(gen_server).

%% API
-export([start_link/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).

-define(SERVER, try_srv).

-record(state, {message = "Hello World!"}).

%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the server
%%--------------------------------------------------------------------
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

%%====================================================================
%% gen_server callbacks
%%====================================================================

%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%% Description: Initiates the server
%%--------------------------------------------------------------------
init([]) ->
{ok, #state{}}.

%%--------------------------------------------------------------------
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} |
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------
handle_call(Request, _From, State) ->
Reply = {State#state.message, Request},
{reply, Reply, State}.

%%--------------------------------------------------------------------
%% Function: handle_cast(Msg, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast(_Msg, State) ->
{noreply, State}.

%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
handle_info(_Info, State) ->
{noreply, State}.

%%--------------------------------------------------------------------
%% Function: terminate(Reason, State) -> void()
%% Description: This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any necessary
%% cleaning up. When it returns, the gen_server terminates with Reason.
%% The return value is ignored.
%%--------------------------------------------------------------------
terminate(_Reason, _State) ->
ok.

%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
%% Description: Convert process state when code is changed
%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
{ok, State}.

%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------

2006/12/22

Erlang fib

-module(fib).
-export([fib/1, fib2/1, start/0, server/1]).

fib(1) -> 1;

fib(2) -> 1;

fib(N) ->
fib(N-1) + fib(N-2).

fib2(N) ->
fib_server ! {N, self()},
receive
{ok, Value} ->
Value;
_ ->
Result = fib2(N - 1) + fib2(N - 2),
fib_server ! {add, N, Result},
Result
end.

server(Dict) ->
receive
{N, Client} ->
case dict:find(N, Dict) of
{ok, Value} ->
Client ! {ok, Value},
fib:server(Dict);
_ -> Client ! nil,
fib:server(Dict)
end;
{add, N, Result} ->
fib:server(dict:store(N, Result, Dict));
dump -> io:format("~p~n", [Dict]),
fib:server(Dict)
end.

start() ->
Dict = dict:new(),
Dict1 = dict:store(1, 1, Dict),
Dict2 = dict:store(2, 1, Dict1),
Pid = spawn(fib, server, [Dict2]),
register(fib_server, Pid).

2006/12/19

Erlang ODBC

Oracle との ODBC 接続がうまくいかなくて悩んでいたけど、ドライバを Microsoft ODBC for Oracle にしたらすんなりつながった。
その後、Oracreのドライバでも {scrollable_cursors, off} を指定してやればつながることが判明。
connect する都度 odbcserver.exe が起動され disconnect しないとそのプロセスが残る。

-module(odbc_test).

-export([main/0]).

main() ->
{ok, Ora} = odbc:connect("DSN=bino;UID=hr;PWD=password;", [{scrollable_cursors, off}]),
{selected, _, [{Aiu}]} = odbc:sql_query(Ora, "select 'あいう' from dual"),
io:format("~s~n", [Aiu]),
odbc:disconnect(Ora).

2006/12/18

Erlang コンカレントプログラミング

Erlang の特徴1つとして Concurrent Programming が挙げられる。OS(カーネル)レベルのスレッドではなく、ユーザレベルのスレッドであるが、非常に軽量で他の言語のスレッドプログラミングでは実現できないような、多重実行も可能らしい。
process(thread)間で共有するデータがない、という理由から、Erlang では thread ではなく process という言葉を使っている。

-module(concurrent_try).

-export([foo/2, run_foo/0]).

foo(_, 0) ->
io:format("おしまい。~n");
foo(Str, RepeatTime) ->
io:format(Str),
foo(Str, RepeatTime - 1).

run_foo() ->
spawn(concurrent_try, foo, ["ひつじ~n", 3]),
spawn(concurrent_try, foo, ["かもめ~n", 3]).

これを実行すると次のようになる。
18> concurrent_try:run_foo().
ひつじ
かもめ
<0.98.0>ひつじ
かもめ

ひつじ
かもめ
19> おしまい。
19> おしまい。


ビルトインファンクションの spawn(Module, Exported_Function, List of Arguments) で新しいプロセス作成する。

出力に混ざってる <0.98.0> は2つめの spawn の返り値で "process identifier" または "pid" である。プロセス固有の識別子である。

メッセージ送受信


プロセス間の共有データのかわりに、プロセス間ではメッセージの送受信が行われる。
receive でメッセージを受信し、! でメッセージを送信する。
server_loop() ->
receive Str ->
io:format("「~s」~n", [Str])
end,
server_loop().

45> ServerPID = spawn(concurrent_try, server_loop, []).
<0.161.0>
46> ServerPID ! "あいう".
「あいう」
[130,160,130,162,130,164]

Erlang

関数を作る


対話環境の中では関数を作ることはできない。ファイルに書いておいて、それをコンパイルすることによって行なう。次のようなファイル(koto.erl)を作成する。C-c C-k でコンパイルされる。
-module(koto).

-export([foo/1]).

foo(X) ->
X + 1.

1> c("c:/home/ancient/letter/erlang/a/koto", [{outdir, "c:/home/ancient/letter/erlang/a/"}]).
{ok,koto}
2> koto:foo(1).
2


-module はモジュールの定義(?)でファイル名と一致する必要があるみたい。
-export はそのモジュールが公開する関数を 関数名/引数の数 のリストで指定する。

Erlang

日本語


Meadow 上なら io:format で日本語を出力できるみたい。
7> io:format("あいう\n").
あいう
ok

2006/12/17

mozex(Firefox & Emacs)


mozex の開発バージョンをダウンロードし、インストール。
設定は画像参照。
~/.emacs で文字コードを指定しておく。

(add-to-list
'file-coding-system-alist
'("/home/ancient/tmp/mozex/.*" . (utf-8-unix . utf-8-unix)))

Erlang

Erlang を試してみようかと思う。

インストール


http://www.erlang.org/download.html からダウンロードした exe を実行すれば、インストール完了。

対話環境


スタートメニューから Erlang を起動すれば、対話環境が起ち上がる。
Ctrl-p, Ctrl-n で入力履歴。Ctrl-a, e, e, f, b は emace と同じ。
末尾はピリオド。
1> 1.
1
2> 1 + 3.
4


Emacs(Meadow)からの実行


Erlang をインストールしたディレクトリが C:\Program Files\erl5.5.2 の場合、.emacs に次のように記述する。
(setq load-path (cons  "C:/Program Files/erl5.5.2/lib/tools-2.5.2/emacs"
load-path))
(setq erlang-root-dir "C:/Program Files/erl5.5.2")
(setq exec-path (cons "C:/Program Files/erl5.5.2/bin" exec-path))
(require 'erlang-start)

M-x erlang-shell で対話環境が起動する。

日本語


Erlang では文字列は数値の配列のようで次のようになる。
2> "あいう".
[130,160,130,162,130,164]

入出力で日本語をまともに扱うには何らかのライブラリが必要なようだ。

友人来訪

飯塚夫妻とニッシーに会った。結婚式以来だろうか。
それぞれの環境や境遇は変わっても、みんなぜんぜん変わってなかったな。

2006/12/16

Barbour CLASSIC MOORLAND

13年ぶりに冬のアウターを買いました。
Barbour のクラシックムーアランド(サイズ36、色オリーブ)です。
この13年間来ていたのは Whole Earth の青いマウンテンパーカー。長い間ありがとうございました。
ゴアテックスからオイルドコットンへの変遷は何を暗示しているのでしょうか。

2006/12/13

exe

うごかない?

(require :trivial-sockets)

(defun main1 ()
(trivial-sockets:with-server (server (:port 8989))
(let ((socket (sb-bsd-sockets:socket-accept server)))
(print (sb-bsd-sockets:socket-peername socket))
(sb-bsd-sockets:socket-close socket))))

(sb-ext:save-lisp-and-die "test.exe" :purify t :toplevel #'main1 :executable t)


これは動く
sbcl --eval "(save-lisp-and-die \"bano.exe\" :toplevel (lambda () (princ \"bano\") (terpri) 0) :executable t)" 

接続してきたアドレスを表示する

(trivial-sockets:with-server (server (:port 8989))
(let ((socket (sb-bsd-sockets:socket-accept server)))
(print (sb-bsd-sockets:socket-peername socket))
(sb-bsd-sockets:socket-close socket)))

2006/12/10

タコのパエリア

タコのパエリアを作りました。大好評でした。

2006/12/01

SBCL 1.0 リリース

SBCL 1.0 がリリースされました。
Shift-JIS external format も実装されています。すばらしい。

2006/11/29

ピネロピへの贈りもの

好きです。

2006/11/26

クリスマスツリー



ようやくクリスマスツリーを買いました。
つれあいが本物っぽい質感のツリーでなければ、とばのるもので。
キティーちゃんは娘によるオリジナルカラーです。

カオマンカイ

カオマンカイを作る。蒸鶏のせご飯です。
おいしかった。
子供用に鷹の爪を少なめにしたけど、これを多めにいれて 香味野菜をたっぷりかけたらさらに美味しいだろうな。また作ってみよう。

2006/11/23

送別会

志村くんの送別会でした。
米田くん涙する。
すべてのものはやがて失われる。だからこそ

2006/11/04

栗ごはんと秋刀魚

栗ごはんと秋刀魚。秋ごはんでした。

2006/11/03

ユニフレームダッチオーブン

ユニフレームダッチオーブンを買ってしまいました。
ロッジプロロジック、コールマンスキレットに続いて3つめの鉄鍋です。
ちょっとした手違いで、キッチンに油をはねとばしながらシーズニングとなってしまいました。

初料理はご飯です。ユニフレームならではの洗剤を使っての油落しをして3合の白米を炊きました。
水加減は米1合につき200cc + α で、強火で炊飯開始。
やがて蓋がカタカタ鳴ってふきこぼれだしたので、弱火にし15分。
最後に10分蒸らしてできあがり。+ α 分の水が余計だったらしくちょっとやわらかめの仕上がりでした。
でも、思いのほか美味しく炊きあがりました。炊飯器にも勝つ勢いです。

2006/10/22

ローズマリーの香りの唐揚げ

ひさしぶりに唐揚げですが、仕上げのラスト5分にローズマリーを5枝とニンニクを皮つきで5つぶくらい入れました。
揚げ時間は30分くらい弱火でじっくり。ちょっと揚げ時間が長すぎて、水分が飛びすぎたみたい。音が変った時点で止めておけばよかったたな。
ローズマリーをいれたせいでとてもいい香です。
昨日の桜チップと今日のローズマリーでとても幸せの空気のキッチンでした。
でも手羽をかじられないように気をつけないとね。

カキのスモーク

スモーク(燻製)に初挑戦です。

  1. 牡蠣を塩水で洗う。
  2. ワインにローズマリーを入れ、煮立ったら牡蠣をさっと茹でる。
  3. ダッチオーブンにアルミ箔をひいてスモークチップを入れる。
  4. 煙が出てきたら、網をひいて牡蠣をならべる。
  5. 少しずらして蓋をして6分くら待つ。
  6. 食べる。
桜チップの香と、中はプリンプリンでとても美味しかった。
食べたあとも桜チップの香がキッチンにだたよっていて、幸せな料理でした。

2006/10/15

全てのクラス

Squeak で全てのクラスをリスト表示する。

aCollection _ Set new.
SystemNavigation default allBehaviorsDo: [:each|
each isMeta ifFalse: [aCollection add: each name]].
aCollection _ aCollection asSortedCollection.
m _ PluggableListMorph on: aCollection list: #yourself selected: #size changeSelected: nil.
m hResizing: #spaceFill.
w _ SystemWindow labelled: '全てのクラス'.
w addMorph: m frame: (0@0 corner: 1@1).
w openInWorld.
^aCollection

yoyo クールピロー mimi

枕を買いました。yoyo クールピロー mimi です。
mini は子供用らしいのですが、低い枕が好きなので mini にしました。
ゲルが入っていてひんやりと気持ちいいです。頭寒足熱です。
寒い季節には表裏を引っくり返せば、ひんやりしなくなります。
ただ、ちょっとカビくさい気が。。。 今日は干しておきます。。。

2006/10/06

asdf-install が動かない

Windows の sbcl で asdf-insatll が動かないので、 asdf-install は使わずに、 ~/.sbclrc に次のコードを書くことに。

(require :asdf)

(loop for dir in (directory (merge-pathnames
"site-systems/*/"
(truename (posix-getenv "SBCL_HOME"))))
do (pushnew dir asdf:*central-registry* :test #'equal))

2006/09/23

鶏の胸肉のレモン風味焼き

鶏の胸肉にレモン汁をよく摺り込み、10分くらいおいた後、塩・コショウをして焼きました。
焼いた後スキレットに残っている肉汁に、味醂と醤油を加えて煮詰めて、ソースを作ります。
鶏とレモンはよくあうのです。

2006/09/18

鮭のムニエル

スキレットで鮭のムニエルを作りました。

  1. 鮭に塩・コショウをし、小麦粉をまぶす。
  2. よく熱したスキレットに鮭を入れ、両面焼き色を付ける。この時中まで火を通す必要はなし。
  3. 鮭を一旦取り出し、スキレットにニンニクをすりつける。
  4. スライスしたジャガイモをスキレットにひきつめ、鮭をその上に置く。キノコも入れる。ローズマリーも入れる。白ワインも適当に入れる。
  5. ふたをして10分間蒸し焼きにする。
鮭がふんわりと美味しくできあがりました。

ヤーン


flickr から Blogger beta にポストできるようになったんだね♪

Dovrak 再び

今年の頭から Dovrak 配列に切り替えて いたけど、仕事で他の人のマシンを使うことが多かったので Qwerty に戻していました。
近頃は他の人のマシンを使う必要もなくなってきたので、 Dovrak に戻そうかと思います。とりあえず、自宅のマシンは戻しました。会社のマシンも戻したいのですが、やはり一時的に開発効率が落ちるので、どうしようか思案中です。
しかし、日本語を入力していると気持ちいいな♪

。。。KINESIS USB モデルがほしくなってきた。

2006/09/17

発熱

瑞が昨夜から熱を出しています。いつものように「はぁーん。。。はぁーん」と言って苦しんでいます。
今日は病院です。

2006/09/16

蒸し鶏

かねてから作ろうと思っていた、蒸し鶏をようやく作りました。
丸鶏は通販で購入。
よく洗ってダッチオーブンに入れて90分。
最初は完全に焼けているような音でしたが、最後にはしっかりとスープが出ていました。
鶏をとりだし、スープの残っているダッチオーブンにお湯を入れ、酒、塩、醤油で味を整えます。そして、麺を入れて3分で美味しいラーメンの完成。いい味が出てました。
しかし、3人家族で丸鶏はやはり食べきれません。

2006/09/10

レンズ豆のピラフ

レンズ豆のピラフを作りました。
米3合
ブイヨン540ccのかわりにコンソメで550cc
レンズ豆の茹で時間は5分くらい。
なかなか美味しくできた。
今度は牛乳を入れつ作ってみたいと思います。

サンリオピューロランド

サンリオピューロランドに行ってきました。
ひそんでいたクマを激写です。

2006/09/04

文字列を大文字小文字大文字小文字...に変換する

文字列を大文字小文字大文字小文字...に変換する。

(defun up-low (word)
(format nil "~{~:@(~C~)~(~C~)~}" (coerce word 'list)))

2006/08/31

CLSQL

CLSQL 3.7.0 がリリースされた。
Win32 の SBCL と CLISP で動くようになった模様。喜ばしい。

バックトレース

バックトレース

(sb-debug:backtrace)
(sb-debug:backtrace-as-list)

普通の関数をジェネリックファンクションに

普通の関数をジェネリックファンクションにする。

(shadow 'length)
(defmethod length (o)
(cl:length o))
(defmethod length ((o symbol))
(length (symbol-name o)))

2006/08/30

デバッグ用セッティング

デバッグ用セッティング

;;デバッグ用セッティング
(proclaim '(optimize (debug 3) (safety 3) (speed 0)))

初める

(require :tama)