Function CERROR

UP


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

影響

*break-on-signals*

存在するハンドラーの束縛

例外

なし。

参考

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)

TOP, Github