Practical Common Lispは非常に詳細ですが、条件システムに慣れるまでに時間がかかることは事実です。Kent Pitman の記事: Exceptional Situations in Lisp およびCondition Handling in the Lisp Language Familyに興味があるかもしれません。
これらは、条件システムとは何か、なぜ必要なのかで参照されています。. このWikibooks エントリや C2 wiki のCommonLispConditionSystemエントリなど、他にも多くの参考文献があります。
再始動の定義
ARESTART-CASE
は基本的に次のように言います。
このフォームを実行しますが、それが条件を通知するかどうかは気にしません。しかし、そうで、その状況から回復したい場合は、問題を回避できるさまざまな方法があります (再試行、無視など)。
通常、コール ポイントで呼び出されているコードのエラーから回復する方法を言うことはできません。言い換えれば、代替パスを提供するためにfilter-evenp
コードを順番にラップする必要があります。あなたの例では、再起動の確立中にエラーを通知するrestart-case
を使用するだけで十分です。CERROR
CONTINUE
(if (evenp x)
(cerror "Ignore even number" 'evenp-error :text x)
(print x))
(cerror ...)
演習として、明示的な構造に置き換えることができますrestart-case
。
次に、コードをテストすると、デバッガーがポップアップ表示され、CONTINUE
再起動が表示されるはずです。独自の再起動を定義した場合は、別の名前を付けることができます。
再起動の呼び出し
あなたの機能では、この時点で確立されていない再起動を呼び出していましたが、再起動と機能の両方の名前付けskip-evenp
に混乱していたと思います。skip-evenp
すべきことは、再起動を呼び出してエラーを処理することです。
ここでは、エラーを通知するコードを続行する必要があるため、実行スタックを巻き戻したくありません。そのため、使用する必要がありますHANDLER-BIND
。
(handler-bind ((evenp-error (lambda (e) (invoke-restart 'continue))))
(filter-evenp '(1 2 3 4)))
1
3
もちろん、匿名ラムダをカスタム関数に抽出することもできます。