3

私がやろうとしていること:simple-error別のエラーでの機能が必要です。私はこれらの理由でこれが欲しいです:

  • の別の句でそれを処理できるようにするためhandler-case

  • メッセージ文字列を何度も指定しないようにするため。

  • エラーが発生したときにデバッガーを呼び出す。

これはデフォルトでは自然に発生せず、この問題に十分な注意を払っていないので、ちょっと戸惑っていますが、これは明らかにそれがどのように機能するかです...私ができることは、後で処理できるエラーを通知することですhandler-caseまたはを使用handler-bindしますが、これは悪いことです。関数がスローされるかどうかを常に覚えているわけではなく、スローされたときに処理するのを忘れると、関数は何も起こらなかったかのように早く戻ります。しかし、の使用を再開するとsimple-error、コードは次のようになります。

...
(signal "Container ~S has no key ~S~&" :container foo :key bar)
...
(signal "Container ~S has no key ~S~&" :container foo :key baz)
...

など、至る所で:/もちろん、メッセージテキストを保存するための変数を専用にしたり、短くするためのマクロを使用したりすることもできますが、これは実際には役に立ちません。解決するのではなく、実際の混乱を隠すだけだからです。問題。

これまでにできること:

(define-condition missing-key (condition)
  ((key :initarg :key
        :accessor key-of)
   (container :initarg :container
              :accessor container-of))
  (:documentation
   "An error rised when a KEY is not in the CONTAINER"
   :report
   #'(lambda (condition stream)
       (unless *print-escape*
         (format stream "~&Container ~S has no key ~S"
                 (container-of condition)
                 (key-of condition))))))

(handler-bind
    ((missing-key
      #'(lambda (condition)
          (invoke-debugger condition))))
  (signal 'missing-key :key 'foo :container 'bar))

ただし、エラーが通知されると、レポート関数が呼び出されることはなく、代わりに一般的なメッセージが出力されます。Condition MISSING-KEY was signalled.

編集:

sdsの回答のおかげで、これは私が今持っているものです:

(define-condition missing-key (error)
  ((key :initarg :key
        :accessor key-of)
   (container :initarg :container
              :accessor container-of))
  (:documentation
   "An error rised when a KEY is not in the CONTAINER")
  (:report
   (lambda (condition stream)
     (format stream "Container ~S has no key ~S"
             (container-of condition)
             (key-of condition)))))

(defmacro signal-missing-key (container key)
  `(let ((*break-on-signals*
          (cond
            ((null *break-on-signals*) 'missing-key)
            ((consp *break-on-signals*)
             (list 'or 'missing-key (cdr *break-on-signals*)))
            (t (list 'or *break-on-signals* 'missing-key)))))
     (signal 'missing-key :key ,container :container ,key)))

より多くの引数をに渡すことで、おそらくより一般的にすることができますsignalが、これは最初にやりたかったことを実行するので、同じことを行うためのより良い方法がない限り、おそらくこれを使用します。

4

3 に答える 3

2

コードは、次の変更を加えて意図したとおりに機能します:remove #'before lambda、remove ~&from format(エラー報告はそれ以上を行います)、句を閉じて:documentation句を開きます:report

(define-condition missing-key (condition)
  ((key :initarg :key
        :accessor key-of)
   (container :initarg :container
              :accessor container-of))
  (:documentation
   "An error rised when a KEY is not in the CONTAINER")
  (:report
   (lambda (condition stream)
       (unless *print-escape*
         (format stream "Container ~S has no key ~S"
                 (container-of condition)
                 (key-of condition))))))
MISSING-KEY
(signal 'missing-key :key 'foo :container 'bar)
==> NIL
(handler-bind
    ((missing-key
      #'(lambda (condition)
          (invoke-debugger condition))))
  (signal 'missing-key :key 'foo :container 'bar))


*** - Container BAR has no key FOO
The following restarts are available:
ABORT          :R1      Abort main loop
Break 1 [46]> 

つまり、signal何も出力せずhandler、デバッガーを呼び出します。

于 2012-11-30T21:05:08.210 に答える
2

条件が別の方法で処理されない限り、デバッガーを呼び出す場合は、errorまたは独自の条件タイプを使用できます。cerrorこれは、の子孫ではない条件でも機能しますsimple-error

に対してもこの動作が必要な場合signalは、変数*break-on-signals*を対応するタイプに設定できます。たとえば、未処理の条件ごとtにデバッガーを呼び出すために、をに設定できます。

于 2012-12-02T02:37:09.797 に答える
1

条件を。ERRORではなくのサブクラスにしますCONDITION。すべての条件がデバッガーによる介入を必要とするエラーであるとは限りません。条件クラス階層は、それらを区別するように設計されています。

于 2012-11-30T19:41:11.037 に答える