2007/05/09

FizzBuzz

Erlang でやっておこう。


-module(a).
-compile(export_all).

m() ->
F = fun
(_, 0, 0) ->
"FizzBuzz";
(_, 0, _) ->
"Fizz";
(_, _, 0) ->
"Buzz";
(X, _, _) ->
integer_to_list(X)
end,
erlang:display([F(X, X rem 3, X rem 5) || X <- lists:seq(1, 100)]).


Common Lisp でも

(loop for i from 1 to 100
collect (cond ((zerop (rem i 15)) "FizzBuzz")
((zerop (rem i 5)) "Buzz")
((zerop (rem i 3)) "Fizz")
(t i)))

Common Lisp ならマクロで

(defmacro f (sym &rest args)
`(cond
((and ,@(mapcar #'(lambda (a)
`(zerop (rem i ,(car a))))
args)
,(format nil "~{~a~}" (mapcar #'cadr args))))
,@(mapcar #'(lambda (a)
`((zerop (rem i ,(car a))) ,(cadr a)))
args)
(t ,sym)))

(loop for i from 1 to 100
collect (f i (3 "Fizz") (5 "Buzz")))

(loop for i from 1 to 100
collect (f i (3 "Fizz") (5 "Buzz") (6 "Huzz")))


いずれも出力部は手をぬきました。

Erlang リモートプロセスは register できない

Erlang ファイルサーバの置き換えですが、次のようにリレーしなくても登録するだけでいけるのでは、と思って試してみました。
register で badarg が発生して、動きませんでした。
register ではローカルプロセスまたはローカルポートしか登録できないのでリレーが必要のなですね。


-module(pseudo_file_server2).
-export([start/0]).

start() ->
%% ローカルノードのファイルサーバを登録解除
unregister(file_server_2),
%% リモートノードのファイルサーバの pid を取得
Pid = rpc:call('ubu@172.22.10.22', erlang, whereis, [file_server_2]),
%% そのプロセスをローカルノードのファイルサーバとして登録
register(file_server_2, Pid).

2007/05/08

Erlang ファイルサーバプロセスの置き換え


やはり Erlang はすごいです。
古い方の Erlang 本『Concurrent Programing in ERLANG』の 11.9 Relay Techniques に載っていたものですが、心底驚きました。
Erlang ではファイルIOは file_server_2 という名前で登録されたプロセス経由で行います。
その file_server_2 をリモートノードのプロセスで置き換えることにより全てのファイルIOがリモートノードが走っているマシンのファイルシステム対しての操作になります。


-module(pseudo_file_server).
-export([start/0, relay/1]).

start() ->
%% ローカルノードのファイルサーバを登録解除
unregister(file_server_2),
%% リモートノードへのリレーループプロセスを開始
Pid = spawn(?MODULE, relay, ['ubu@172.22.10.22']),
%% そのプロセスをローカルノードのファイルサーバとして登録
register(file_server_2, Pid).

relay(Node) ->
%% リモートノードのファイルサーバの pid を取得
Pid = rpc:call(Node, erlang, whereis, [file_server_2]),
%% リレーループ開始
loop(Pid).

loop(Pid) ->
%% ファイルサーバとして受信したものをリモートノードへリレー
receive
Any ->
Pid ! Any
end,
loop(Pid).

次は実行例です。

2> pseudo_file_server:start().
ture
3> file:write_file("/tmp/a.txt", "hello").
ok

/tmp/a.txt はローカルのファイルシステムではなく、リモートマシンファイルシステム上さ作成されます。
なんと素晴しい。
本の中ではファイルシステムを持たない組み込みシステム等でも、このテクニックによりファイルシステムを使える、とういような説明でした。
『Concurrent Programing in ERLANG』は第一版が1993年、第二版が1996年に出版されています。これまでの間、私たちはいったい何をしていたのでしょうか。
単にマルチコアの普及により Erlang のアーキテクチャが生きるようになっただけなのでしょうが。
素敵ですね。

GWのまとめ

GWのまとめ

髪を切った。
近所の公園がオープンした。
姪の百恵ちゃん誕生。
ポークスペアリブ。
ずっと早起き。

たいしてまとめるべきものもないな。

AUCTeX の設定

~/.emacs


;;;;AUCTeX
(load "auctex.el" nil t t)
(load "preview-latex.el" nil t t)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)
(setq TeX-default-mode 'japanese-latex-mode)
(setq japanese-TeX-command-default "pTeX")
(setq japanese-LaTeX-command-default "pLaTeX")
(setq japanese-LaTeX-default-style "jsarticle")
(setq TeX-print-command "%(o?)dvips -P%p %r %s")
(add-hook 'TeX-mode-hook
(function
(lambda ()
(TeX-source-specials-mode 1)
;; (add-to-list 'TeX-output-view-style
;; '("^dvi$" "." "dvipdfmx %dS %d && acroread %s.pdf"))
(local-set-key "\C-c\C-i" 'TeX-complete-symbol)
;; (local-set-key "\C-@" 'TeX-next-error))))
)))

色付けおかしいですね。シングルクォートが文字列あつかいされている。

Yaws 組み込みモードの設定

Yaws 組み込みモードで他のマシンからアクセスできるようにするには、listen と servername の指定も必要です。


SC = [{port, 8880}, % ポート番号
{servername, "www.example.com"}, % サーバ名
{listen, {0, 0, 0, 0}}], % リッスンアドレス
GC = [{logdir, "/tmp"}], % グローバル設定
yaws:start_embedded("/var/www", SC, GC). % 組み込みモードでスタート

2007/05/07

Erlang io の引数に lists:flatten は必要ない

io_lib:format/2 の返り値が、単なる文字列ではなく、文字と文字列のリストになるのは不便なのに何故だろう、と思っていました。
ふとしたことで文字と文字列のリストそのままで出力できることに気づきました。
lists:flatten はいらないのですね。
file:write_file/2 でもネストしたリストそのままで大丈夫でした。


49> io_lib:format("Hello ~s!~n", ["World"]).
[72,101,108,108,111,32,"World",33,"\n"]
50> io:format([72,101,108,108,111,32,"World",33,"\n"]).
Hello World!
ok

そういえば、次のようなのもOKなんですよね。

51> "Hello" " " "World" "!\n".
"Hello World!\n"