% Function CERROR
Function CERROR
cerror
continue-format-control datum &rest
arguments
=> nil
continue-format-control - format-control
datum, arguments - コンディション指定子であり、標準の型はsimple-error
。
cerror
は、datumによって指定されたコンディションを
効果的にerror
で実行します。
どこかの関数で暗黙的にerror
が呼ばれたとき、
もしそのコンディションが捕捉されなかったときは、
(invoke-debugger condition)
が実行されます。
シグナルが通知され、
そしてデバッガーに到達したとき、
continue
restart
を使うことで
コードの実行を継続することができます
(例えばcerror
から戻ります)。
もしdatumがコンディションならargumentsを指定できますが、 それはcontinue-format-controlとの組み合わせでのみ使用されます。
(defun real-sqrt (n)
(when (minusp n)
(setq n (- n))
(cerror "Return sqrt(~D) instead." "Tried to take sqrt(-~D)." n))
(sqrt n))
(real-sqrt 4)
=> 2.0
(real-sqrt -9)
>> Correctable error in REAL-SQRT: Tried to take sqrt(-9).
>> Restart options:
>> 1: Return sqrt(9) instead.
>> 2: Top level.
>> Debug> :continue 1
=> 3.0
(define-condition not-a-number (error)
((argument :reader not-a-number-argument :initarg :argument))
(:report (lambda (condition stream)
(format stream "~S is not a number."
(not-a-number-argument condition)))))
(defun assure-number (n)
(loop (when (numberp n) (return n))
(cerror "Enter a number."
'not-a-number :argument n)
(format t "~&Type a number: ")
(setq n (read))
(fresh-line)))
(assure-number 'a)
>> Correctable error in ASSURE-NUMBER: A is not a number.
>> Restart options:
>> 1: Enter a number.
>> 2: Top level.
>> Debug> :continue 1
>> Type a number: 1/2
=> 1/2
(defun assure-large-number (n)
(loop (when (and (numberp n) (> n 73)) (return n))
(cerror "Enter a number~:[~; a bit larger than ~D~]."
"~*~A is not a large number."
(numberp n) n)
(format t "~&Type a large number: ")
(setq n (read))
(fresh-line)))
(assure-large-number 10000)
=> 10000
(assure-large-number 'a)
>> Correctable error in ASSURE-LARGE-NUMBER: A is not a large number.
>> Restart options:
>> 1: Enter a number.
>> 2: Top level.
>> Debug> :continue 1
>> Type a large number: 88
=> 88
(assure-large-number 37)
>> Correctable error in ASSURE-LARGE-NUMBER: 37 is not a large number.
>> Restart options:
>> 1: Enter a number a bit larger than 37.
>> 2: Top level.
>> Debug> :continue 1
>> Type a large number: 259
=> 259
(define-condition not-a-large-number (error)
((argument :reader not-a-large-number-argument :initarg :argument))
(:report (lambda (condition stream)
(format stream "~S is not a large number."
(not-a-large-number-argument condition)))))
(defun assure-large-number (n)
(loop (when (and (numberp n) (> n 73)) (return n))
(cerror "Enter a number~3*~:[~; a bit larger than ~*~D~]."
'not-a-large-number
:argument n
:ignore (numberp n)
:ignore n
:allow-other-keys t)
(format t "~&Type a large number: ")
(setq n (read))
(fresh-line)))
(assure-large-number 'a)
>> Correctable error in ASSURE-LARGE-NUMBER: A is not a large number.
>> Restart options:
>> 1: Enter a number.
>> 2: Top level.
>> Debug> :continue 1
>> Type a large number: 88
=> 88
(assure-large-number 37)
>> Correctable error in ASSURE-LARGE-NUMBER: A is not a large number.
>> Restart options:
>> 1: Enter a number a bit larger than 37.
>> 2: Top level.
>> Debug> :continue 1
>> Type a large number: 259
=> 259
存在するハンドラーの束縛
なし。
error
,
format
,
handler-bind
,
*break-on-signals*
,
simple-type-error
もしdatumが文字列ではなくコンディションの型のときは、
format
の命令である~*
がcontinue-format-control内で
初期化引数リストのキーワードを無視するためには特に有効です。
例えば下記の通り。
(cerror "enter a new value to replace ~*~s"
'not-a-number
:argument a)