Shammer's Philosophy

My private adversaria

標準出力交換

Lisp では、

(format t "abcdefg")

というようにすると、標準出力に abcdefg と出力される。これ自体は別に特別でも何でもない。しかし、内部では format は出力先に *standard-output* を指定しているように見える。以下のようなコードを書くと、

(with-open-file (f "xxxxxxx.txt" :direction :output
		   :if-does-not-exist :create
		   :if-exists :supersede)
  (let ((*standard-output* f))
    (format t "0123456789")
    (format t "xxx")))
(format t "OK")
(quit)

画面に 0123456789xxx は出力されず、OK のみが出力される。そして、xxxxxxx.txt というファイルが作成され、そこに 0123456789xxx が記録されている。
これの強力なところは、ある特定のスコープだけで標準出力が入れ替わること。上記例ではそのまま let のブロックで format を呼び出しているが、ここを load とかにして、load されるファイルで format したものもこの変更が有効。しかも、let を抜ければその変更は自動でもとに戻る。こんなことできるとは新鮮に感じる。Java や C でもできるのだろうか。。。System.in や System.out に何か代入した時点でエラーとかになりそう。やってないけれども。