condition-restart をリリースしました

netinstaller 用 packages.l からどうぞ。

インストールして *scratch* から↓やってみたらなんとなくわかると思いたい。

(require "condition-restart")
(require "condition-restart-support")
(restart:setup-key-bindings)

(let ((age -3))
  (assert (and (numberp age) (<= 0 age 127)) (age))
  age)

再起動システム

再起動ってのは、エラーを投げる側(signaler)でエラーに対処する方法を用意しておいて、エラーを受け取った側(handler)でどう対処するか選べるような仕組みです。
一応 Common Lisp のと互換になってるはずです。

再起動使うだけなら condition-restart.l を読み込んでおけば使えます(トップレベルでのー、は除く)。

トップレベルで再起動を選択

Common Lisp だとエラーがトップレベルまで飛んできたら、デバッガが起動してそっから再起動を選べるんですが、xyzzy にはデバッガがないもんで再起動を選ぶだけの簡単なものを作りました。

(require "condition-restart-support")
(restart:setup-key-bindings)

上記の設定をしておくと、以下のキーバインドを変更します。

  • lisp-mode
    • C-M-x: eval-defun
    • C-x C-e: eval-last-sexp
  • lisp-interaction-mode
    • C-j: eval-print-last-sexp

変更後のコマンド(restart:eval-***)は標準の同名コマンドに、エラーが飛んできたときに再起動を選択できるようにしたものです。

assert と check-type

トップレベルで再起動を選択できるように設定して、こんなの↓を評価すると

(let ((name :fred))
  (assert (stringp name) ;TEST-FORM
          (name) ;PLACES
          "名前が変です: ~S" name) ;DATUM & ARGS
  (format t "His name is ~A" name))

ウィンドウが分割されてこんなの↓が表示されて、ミニバッファで起動する再起動の番号を入力できます。

simple-error:
    名前が変です: :fred

  0 [continue] 値を変更してやり直す。(name)
  1 [abort   ] やめる。

1 [abort] を選ぶと、処理を中止します。C-g でも abort できます。たぶん quit と一緒です。
0 [continue] を選ぶと name の新しい値を聞いてくるので、てきとーな式を入力すると assert は name を入力された値で置き換えて最初からやり直します。

assert は (stringp name) が true になるまでこれを繰り返すので、assert から制御が返るときには必ず name が stringp になるよ、というものです。

check-type も似たようなものです。

へなリファ

「へなちょこリファレンス形式のリファレンス」が長いんで略しましたごめんなさい。

${XYZZY}/reference/condition-restart.xml というファイルがあるんで、xy-reference と reference.xml を netinstaller から入手して

(require "xy-reference")
(xy-reference:2txt)

しておけば info-modoki-mode から restart-case とか invoke-restart とか assert とか見れるようになるはずです。