我在空闲时间学习 Common Lisp,并对条件系统有疑问。
当我们在 common lisp 中处理错误时,我们在处理程序中指定错误类型来确定要处理哪个错误。在引发和处理错误之间,我可以进行一些重新启动(例如使用 restart-case),但我无法在重新启动中指定错误类型。
例如,假设我有一个函数,它接受一个字符串和一个流,将字符串发送到流并从流中读取响应并返回它。假设如果我的消息错误,我会从流中读取错误响应。我想引发一个错误并绑定一个重新启动,要求新消息,如下所示:
(defun process-message (stream raw-message)
(let ((response (get-response stream raw-message)))
(restart-case
(when (response-error-p response)
(error 'message-error :text response))
(change-raw-message (msg)
(process-message stream msg)))))
现在假设消息很复杂并且我得到了另一个函数send-command
在更高级别,可以从某些参数创建消息并调用进程消息。我想再绑定一次重启recreate-command-message
这将允许用户从参数发送新命令,如果'message-error
获得。此重新启动可以放置在重新启动案例中process-message
,但这并不完全正确,因为process-message
不应该知道这样的高级功能send-command
并且返回值可能不同。
但现在流错误(如EOF等)将被抛出recreate-command-message
如果套接字失败recreate-command-message
重启在某些超高级中会可用socket-error
处理程序并且此重新启动将是无用的并且是惯用的错误。
这是一个程序设计问题吗?应该设计一个程序来避免此类问题,或者我只是找不到如何将重新启动绑定到错误类型,或者我不正确理解条件系统?
Thanks.
也许这有帮助:
(define-condition low-level-error (simple-error)
()
(:report (lambda (c s)
(format s "low level error."))))
(define-condition high-level-error (simple-error)
()
(:report (lambda (c s)
(format s "high level error."))))
(defun low-level (errorp)
(restart-case
(when errorp (error 'low-level-error))
(go-on ()
:report "go on from low-level"
t)))
(defun high-level (high-level-error-p low-level-error-p)
(restart-case
(progn
(when high-level-error-p (error 'high-level-error))
(low-level low-level-error-p))
(go-on ()
:report "go on from high level"
:test (lambda (c) (typep c 'high-level-error))
t)))
尝试调用high-level
具有不同的值(t
or nil
)获取其参数,并在调试器中检查相应的可用重新启动是否满足您的需要。仅当发出高级别错误信号时才会看到高级别重新启动,并且由于较高级别的重新启动保留在堆栈中,因此较低级别的函数不必知道要恢复的高级别方法。
对于您的特定用例,如果我理解正确的话,这意味着:建立您的recreate-command-message
重新启动以重新调用process-message
in send-command
,并使其仅适用于高级错误。
正如您在阅读上面链接的 PCL 章节 Vsevolod 后可能知道的那样,实际处理这些错误,即决定调用哪个重新启动,是通过handler-bind
and handler-case
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)