我正在尝试做什么:
我希望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
来使它更通用,但是这样做我最初想做的事情,所以,除非有更好的方法做同样的事情,我可能会只是用这个。
答案 0 :(得分:2)
您的代码按预期工作,并进行了以下修改:在#'
之前删除lambda
,从~&
删除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
调用调试器。
答案 1 :(得分:2)
如果您希望调用调试器,则可以将error
或cerror
与您自己的条件类型一起使用,除非以其他方式处理条件。这也适用于不是simple-error
的后代的条件。
如果您对signal
也有此行为,则可以将变量*break-on-signals*
设置为相应的类型。例如,您可以将其设置为t
,以便为每个未处理的条件调用调试器。
答案 2 :(得分:1)
使您的条件成为ERROR
的子类,而不是CONDITION
。并非所有条件都是需要通过调试器进行干预的错误,条件类层次结构旨在区分它们。