2008年1月10日木曜日

Chapter 14 Files and File I/O

前説

特になし。

Reading File Data

SLIMEって、openでファイルを指定するとき、補完してくれるんだ。少し幸せな気持になった。

CL-USER> (let ((in (open "/var/log/messages" :if-does-not-exist nil)))
(when in
(format t "~a~%" (read-line in))
(close in)))
Jan 9 07:39:59 ubuntu syslogd 1.4.1#17ubuntu7.1: restart.
T
CL-USER>

の"/var/log/messages"のところ。


CL-USER> (let ((in (open "/var/log/messages" :if-does-not-exist nil)))
(when in
(loop for line = (read-line in nil)
while line do (format t "~a~%" line))
(close in)))
Jan 9 07:39:59 ubuntu syslogd 1.4.1#17ubuntu7.1: restart.
...
Jan 10 21:46:38 ubuntu -- MARK --
T
CL-USER>


doで書いてみる。

CL-USER> (let ((in (open "/var/log/messages" :if-does-not-exist nil)))
(do ((line (read-line in nil) (read-line in nil)))
((null line) (close in))
(format t "~a~%" line)))

READ-LINEが繰り返しているのが嫌ですが、普通に書けます。
LOOPをみて思うのは、読むのは簡単、だけど、書くのは怖い、ということです。
慣れの問題ですが、それ以外にもあるような。
抽象構文木っぽくないものを書くと、どのトークンがどういう意味なのか何なのか、何をしていいのかしちゃいけないのか、ということがわからなくて不安になるように思います。doの場合、構文は、

(do (variable-definition*)
(end-test-form result-form*)
statement*)

さえおさえれば、後は括弧で構文木を書いていけばいいやということでなぜか安心する(DOじゃなくて再帰ならさらに安心) 。しかし、Cライクな構文に慣れた人にとっては、繰り返しを書くのにいちいちDO的や再帰にするのは、ゲンナリ、という気がします。たかだか繰り返し表現でゲンナリされるのはもったいないからLOOP全面出し、という戦略がこの本にはあるのかもしれません。

そういう意味では、Schemeが再帰に繰り返しの基礎を置き、末尾再帰で効率確保というのは、それはそれでよいことですが、それは言語コアとしてということであって、ライブラリとしてLOOPのようなものを早めに前面に出した方が世渡り上手かもしれません。それはマクロのパワーの現れでもあるのですから。

あれ? 上のDO、LETいらないのでは。ああ、そうか。DOの変数定義は、前のイテレーションの値しか引けないから、lineの初期値に困るから、LETがあった方がいいですね。

う、仕事せねば。中断。
再開。

((a b) (c d))をreadすると、((A B) (C D))がprintされる。quoteはいらんのか?
そうか、トップレベルでREADを使うと、REPLじゃなくてRPLになるからいらんのか。(REの結果がREAD)


Reading Binary Data
Bulk Reads
File Output

特になし。


Closing Files

UNWIND-PROTECTの詳細は、Chapter 20で。


続く。

0 件のコメント: