我在空闲时间学习普通的 lisp,并对条件系统有疑问。

当我们在 common lisp 中处理错误时,我们在处理程序中指定 error-type 以确定要处理的错误。在引发和处理错误之间,我可以进行一些重启(例如使用重启案例),但我无法在重启中指定错误类型。

例如,假设我有一个函数,它接受一个字符串和一个流,将字符串发送到流并从流中读取响应并返回它。假设如果我的消息是错误的,我会从流中读取错误响应。我想引发一个错误并绑定(bind)一个重新启动,要求提供新消息,如下所示:

(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,它可以从一些参数创建消息并调用 process-message。我想绑定(bind)另一个重新启动 recreate-command-message,如果 'message-error 获取,它将允许用户从参数发送新命令。此重启可能位于 process-message 处的 restart-case 中,但它并不完全正确,因为 process-message 不应该知道像 send-command 这样的高级函数,并且返回值可能不同。

但是现在流错误(例如 EOF 等)将被抛出 throw recreate-command-message 并且如果 socket 失败,recreate-command-message 重启将在某些超高级别的 socket-error 处理程序中可用,并且这种重启将是无用的并且惯用错误。

这是一个程序设计问题,应该设计一个程序来避免此类问题,或者我只是找不到如何将重新启动绑定(bind)到错误类型或者我不正确理解条件系统?

谢谢。

最佳答案

也许这有帮助:

(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-levelt )为其参数调用 nil ,并检查调试器中相应的可用重启是否满足您的需要。只有在发出高级别错误信号时才会看到高级别重启,并且由于更高级别的重启保持在堆栈中,低级别函数将不必知道高级别方法来恢复。

对于您的特定用例,如果我理解正确,这将意味着:建立您的 recreate-command-message 重新启动以重新调用 process-message 中的 send-command ,并使其仅可用于高级错误。

正如您在阅读上面链接的 PCL 章节 Vsevolod 后可能知道的那样,实际处理这些错误,即决定调用哪个重新启动,是通过 handler-bindhandler-case 完成的。

关于error-handling - 常见的 lisp 重启到条件绑定(bind),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15470619/

10-11 02:53