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
1)
(read-eval-print-loop + 'a 3)
(the function + was of the wrong type.
>> Error: The argument, A, to function expected a number.
>> The continue, type :CONTINUE followed by an option number:
>> To 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."))))))
(-2
COMPUTE-FIXNUM-POWER-OFdefun compute-power-of-2 (x)
(or (compute-fixnum-power-of-2 x) 'something big))
(-2
COMPUTE-POWER-OF-2 10)
(compute-power-of1024
-2 10000)
(compute-power-of2 is too large.
>> Error: Power of continue, type :CONTINUE followed by an option number.
>> To 1: Give up on computing 2^10000.
>> 2: Return to Lisp Toplevel
>> 1
>> Debug> :continue => 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 ()
(,lambda (stream)
:report (format stream ,format-control ,@format-arguments))
(values nil t)))) (
例外的な状況では第二返却値がt
になるため、 通常の場合は第二返却値を省略するかnil
にして、 2つの状況を区別できるようにするのが一般的です(ただし必須ではありません)。