Common lisp 是否创建一个条件,在发出信号时调用调试器?

Common lisp 是否创建一个条件,在发出信号时调用调试器?,common-lisp,Common Lisp,我想做的是: 我想在另一个错误中使用simple error的功能。我之所以要这样做,原因如下: 能够在处理程序案例的单独子句中处理它 要避免反复指定消息字符串 在错误发生时调用调试器 我有点困惑,这不是自然发生的默认情况,从来没有足够的重视这个问题,但这显然是它的功能。。。我能做的是发出一个错误信号,稍后我可以用处理程序case或处理程序bind来处理,但这很糟糕,因为我不总是记得函数是否抛出,当它确实抛出时,但我忘了处理它,函数只是提前返回,就好像什么也没发生一样。但是如果我继续使用简单

我想做的是: 我想在另一个错误中使用
simple error
的功能。我之所以要这样做,原因如下:

  • 能够在
    处理程序案例
    的单独子句中处理它

  • 要避免反复指定消息字符串

  • 在错误发生时调用调试器

我有点困惑,这不是自然发生的默认情况,从来没有足够的重视这个问题,但这显然是它的功能。。。我能做的是发出一个错误信号,稍后我可以用
处理程序case
处理程序bind
来处理,但这很糟糕,因为我不总是记得函数是否抛出,当它确实抛出时,但我忘了处理它,函数只是提前返回,就好像什么也没发生一样。但是如果我继续使用
简单错误
,那么我的代码开始如下所示:

...
(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))
然而,发生的事情是报告函数从未被调用。。。当发出错误信号时,它会打印一条通用消息,显示“条件缺失-键已发出信号”。

编辑:

感谢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)))

我可能会通过将更多参数向下传递到
信号
,使其更通用,但这正是我最初想要做的,因此,除非有更好的方法来做同样的事情,否则我可能会使用它。

将您的条件作为
错误
的子类,而不是
条件
。并非所有条件都是需要通过调试器干预的错误,条件类层次结构旨在区分它们。

通过以下修改,您的代码可以按预期工作:删除
#'
lambda
之前,从
格式中删除
~&
(错误报告会执行此操作和其他操作),请关闭
: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]> 
i、 例如,
signal
只打印调用调试器的
handler

如果不希望调用调试器,则可以使用或与自己的条件类型一起使用,除非以其他方式处理这些条件。这也适用于不是调试器的后代的条件


如果您也需要此行为,您可以将变量设置为相应的类型。例如,您可以将其设置为
t
,以便为每个未处理的条件调用调试器。

我没有仔细阅读您的问题,但您不能将其设置为条件的类型,使其在发出信号时进入调试器吗这是我在浏览你的问题时想到的第一件事。这是Lisp,当然还有其他方法可以实现你想要的,但我不知道一个更简单的方法。再看一次这个问题,我想我不太明白。为什么你需要上面的宏,是什么阻止你只设置
*break-在信号上*
简单错误
(或者甚至
t
,如果您希望针对每个未处理的情况)?如果你真的想了解这一点,你甚至可以定义一个新的类型来检查插槽
中断
或你的条件中的某个东西,这样调试器只在你用
:中断t
发信号的情况下才被输入。我不知怎的看不到问题。(或者你需要类似的示例代码吗?)据我所知,通常是
error
cerror
(您也可以使用自己的条件类型,而不仅仅是
error
简单错误的后代)用来代替
信号
来获得你想要的行为。因此,是的,它的使用方式与其他语言有点不同。我明白你的意思,但将
*中断信号*
设置为
错误
来获得你想要的所有错误条件下的行为,即使只是
信号
发光二极管。好的,我会的然后回答。然后你需要继承
简单错误
(或者
错误
或者
错误
,如果你想继续),而不是
条件