Shammer's Philosophy

My private adversaria

with-open-fileマクロ

ファイルを扱う際には、openやcloseを隠蔽している、with-open-fileマクロというのを使うのが主流のようだ。マクロは、macroexpand関数で展開できるらしい。試しにwith-open-fileを展開してみると、

? (macroexpand '(with-open-file (stream path :direction :input)))
(LET (#:G19 #:G20) (UNWIND-PROTECT (MULTIPLE-VALUE-PROG1 (LET ((STREAM (SETQ #:G19 (OPEN PATH :DIRECTION :INPUT))))) (SETQ #:G20 T)) (WHEN #:G19 (CLOSE #:G19 :ABORT (NULL #:G20)))))
T
?

となった。・・・よくわからないのが出てきたぞ・・・unwind-protectとか、mutiple-value-prog1とか・・・
こいつらはおいおい調べていこう。

実際にwith-open-fileを使ってみる。昨日の例だと、複数行あるテキストも1行しか出力しなかったので、EOFまで出力するようなサンプルを作成。こんな感じになった。

(defun cat (path)
  (with-open-file (stream path :direction :input)
    (loop
	 (let ((line (read-line stream nil 'eof)))
	   (if (eql line 'eof) (return))
	   (format t "~A~%" line)))))

unwind-protectは、Javaでいうところのtry/catch/finallyに似ている概念かもしれない。絶対にクローズさせるようになっているのかも。