% Macro WITH-SIMPLE-RESTART
Macro WITH-SIMPLE-RESTART
with-simple-restart
(name format-control format-argument*) form*
=> result
name - シンボル
format-control - format-control
format-argument - オブジェクト(これはformat-arguments)
form - 暗黙のprogn
result - 通常の状況ではformによる返却値であり、
nameというrestart
が起動されたことによる例外的な状況では、
2つの値nil
とt
が返却されます。
with-simple-restart
はrestart
を確立します。
もしnameで指定されたrestart
がform実行中に起動されなかったら、
formの最後から返却される全ての値が返却されます。
もしnameで指定されたrestart
がform実行中に起動されたら、
制御はwith-simple-restart
へ遷移し、
2つの値nil
とt
が返却されます。
もしnameがnil
のとき、
匿名のrestart
が確立されます。
format-controlとformat-argumentは、
restart
の報告のときに使用されます。
(defun read-eval-print-loop (level)
(with-simple-restart (abort "Exit command level ~D." level)
(loop
(with-simple-restart (abort "Return to command level ~D." level)
(let ((form (prog2 (fresh-line) (read) (fresh-line))))
(prin1 (eval form)))))))
=> READ-EVAL-PRINT-LOOP
(read-eval-print-loop 1)
(+ 'a 3)
>> Error: The argument, A, to the function + was of the wrong type.
>> The function expected a number.
>> To continue, type :CONTINUE followed by an option number:
>> 1: Specify a value to use this time.
>> 2: Return to command level 1.
>> 3: Exit command level 1.
>> 4: Return to Lisp Toplevel.
(defun compute-fixnum-power-of-2 (x)
(with-simple-restart (nil "Give up on computing 2^~D." x)
(let ((result 1))
(dotimes (i x result)
(setq result (* 2 result))
(unless (fixnump result)
(error "Power of 2 is too large."))))))
COMPUTE-FIXNUM-POWER-OF-2
(defun compute-power-of-2 (x)
(or (compute-fixnum-power-of-2 x) 'something big))
COMPUTE-POWER-OF-2
(compute-power-of-2 10)
1024
(compute-power-of-2 10000)
>> Error: Power of 2 is too large.
>> To continue, type :CONTINUE followed by an option number.
>> 1: Give up on computing 2^10000.
>> 2: Return to Lisp Toplevel
>> Debug> :continue 1
=> SOMETHING-BIG
なし。
なし。
なし。
with-simple-restart
は、
もっとも一般的に使用されるrestart-case
の
短縮形のひとつです。
with-simple-restart
は次のように定義できます。
(defmacro with-simple-restart ((restart-name format-control
&rest format-arguments)
&body forms)
`(restart-case (progn ,@forms)
(,restart-name ()
:report (lambda (stream)
(format stream ,format-control ,@format-arguments))
(values nil t))))
例外的な状況では第二返却値がt
になるため、
通常の場合は第二返却値を省略するかnil
にして、
2つの状況を区別できるようにするのが一般的です(ただし必須ではありません)。