(rontolisp) docs
← 特殊形式

unwind-protect

(unwind-protect protected cleanup...)

protected フォームを評価してその値を返し、そこからのあらゆる脱出時に cleanup フォームを実行します: 通常の復帰、error による巻き戻し、return/return-from による非局所脱出のいずれでも実行されます。cleanup の値は捨てられます — 値の個数も含めて捨てられるため、protected フォームが多値を返す場合は、cleanup が何個の値を返そうとそのすべてが返ります。cleanup フォーム自身がエラーを通知した場合は、進行中の脱出を置き換えます(Common Lisp と同じく、新しいエラーが勝ちます)。

unwind-protect--no-gc(コンパイルエラー)を除くすべてのバックエンドでサポートされます。wasm-GC バックエンド(Preview 1 と --component)では WebAssembly の exception-handling プロポーザルを通じてコンパイルされるため、これを使うプログラムの実行には wasmtime 37+ が必要です。捕捉/cleanup フォームを使わないプログラムは従来とバイト単位で同一であり、コマンドラインも変わりません。相違点: cleanup はシグナルされたエラーの巻き戻し(error/signal)では実行されますが、ランタイムトラップ((car 5) のような型エラー、整数のゼロ除算)は依然として cleanup を実行せずインスタンスを終了させます — インタプリタと JVM はこれらでも cleanup を実行します。with-* マクロ(with-open-filewith-output-to-stringwith-input-from-string、および usocket:with-* ファミリ)はすべてのバックエンドで unwind-protect に展開されるため、あらゆる脱出時にハンドルを解放します。したがって wasm-GC では with-* を使うプログラムも EH モードでコンパイルされます。

cleanup 自身が値を返す場合 — 解放ヘルパーの慣用句である「何も返さない」(values) を含めて — protected フォームの値が切り詰められることはありません:

protected フォームが return で早期脱出する場合も cleanup は実行されます:

捕捉されない error はプログラムを中断するため、エラー経路は静的な例で示します:

CL-USER> (unwind-protect (error "boom") (print :cleaned))
:cleaned
Error: boom