Common Lisp Break-If-There-Error-Error宏包装器(带Clack webserver)

时间:2018-02-21 03:11:58

标签: macros common-lisp break

我正在尝试编写一个宏,将一个或多个表单包装到其正文中并尝试执行它们。我想将宏放入调试器,类似于执行(break)时的情况。

问题在于我不熟悉Common Lisp用于捕获错误的工具。我可以使用CL的哪些功能来实现这一目标?

使用示例: (break-on-error (start '#:blogdemo :port 8080))

1 个答案:

答案 0 :(得分:2)

以上评论是正确的:网络服务器可能被配置为停止捕获和记录错误,而是中断。

但请注意,BREAK始终保证始终进入调试器,并且您始终可以在要测试的表单周围绑定新的处理程序。例如,假设您有此处理程序捕获错误并将其记录到标准输出:

(defun main ()
  (handler-case (my-function) 
    (error (e) 
      (print `(:error ,e)))))

另外,让我们定义my-function

(defun my-function ()
  (if (zerop (random 2))
    (print "success")
    (error "failure")))

如果多次致电main,您会看到"success"或错误正在打印到标准输出。 如果您希望在my-function失败时中断,尽管在main中建立了处理程序,您可以按如下方式重新定义my-function

(defun my-function ()
  (handler-bind ((error (lambda (condition) (break))))
    (if (zerop (random 2))
      (print "success")
      (error "failure"))))

样式不是很好(条件被忽略等),但毕竟这只是用于调试。 现在,该函数将在出错时进入调试器。

您可以为此编写宏。首先,将我们的处理程序定义为外部函数(用于重用等。此外,宏中的代码越少越好)。顺便说一句,这次,条件不会被忽略,而是打印给用户。

(defun break-on-error (condition)
  (break "~a" condition))

宏只是:

(defmacro with-active-debugger (&body body)
  `(handler-bind ((error #'break-on-error))
      ,@body))

可以重写该功能:

(defun my-function ()
  (with-active-debugger 
    (if (zerop (random 2))
      (print "success")
      (error "failure"))))