我正在尝试做的事情:我想要simple-error
另一个错误中的功能。我想要这个,原因如下:
能够在 的单独子句中处理它
handler-case
。避免一遍又一遍地指定消息字符串...
在发生错误时调用调试器。
我有点困惑,默认情况下这不会自然发生,从未对这个问题给予足够的关注,但这显然是它的功能......我能做的是发出错误信号,稍后我可以处理使用handler-case
or 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
,但这正是我最初想做的事情,所以,除非有更好的方法来做同样的事情,否则我可能会使用它。