with-open-file
(with-open-file (stream filename options...) body...)
filename で指定されたファイルを開き、開いたストリームを stream に束縛し、その束縛のもとで本体のフォームを評価して、あとでファイルを閉じ、最後の本体フォームの値を返します。インタープリタと JVM では展開が本体を unwind-protect で包むため、あらゆる脱出時(通常復帰、本体内でのエラー通知、return/return-from)にファイルが閉じられます。これは exception-handling サポートの導入以降、wasm-GC を含むすべてのバックエンドで成り立ちます(wasm-GC では with-open-file を使うプログラムは EH モードでコンパイルされます)。サポートされるオプションは :direction(:input(デフォルト)、:output または :io)、:element-type('character(デフォルト。テキストストリーム)または整数型(read-byte/write-byte 用のバイナリストリーム。'(unsigned-byte 8) は要素ごとに 1 オクテット、より広い型や符号付きの型は open が説明する要素で、コンパイル後のバックエンドではリテラルで書く必要があります))、および open が説明する :if-exists / :if-does-not-exist / :external-format のテーブル(:if-exists :append と :overwrite を含む)です。オプションの値は計算された値でも構いません。オプションを引数として受け取り下位に渡す関数は、移植性のあるファイル操作ラッパーがファイルを開く際の定型であり、そうした値はフォームの実行時に読み取られ、対応するリテラル形にディスパッチされます。リテラルの値は従来どおりコンパイル時に解決されるため、通常の書き方のコンパイル結果は変わりません。サポート範囲外の値はフォームの実行時にエラーを通知します。単純な open/close のペアに展開されるため、特別なストリーム型は関与しません。
ファイルシステムに触れるため、with-open-file はここでは実行可能な例ではなく静的に示します。
(with-open-file (s "out.txt" :direction :output)
(write-line "hello" s))
(with-open-file (s "out.txt" :direction :input)
(read-line s)) ; => "hello"
(with-open-file (s "out.bin" :direction :output :element-type '(unsigned-byte 8))
(write-byte 255 s)) ; => 255
(with-open-file (s "out.txt" :direction :output :if-exists :append)
(write-line "again" s))
(defun read-first-line (path element-type)
(with-open-file (s path :direction :input :element-type element-type)
(read-line s)))