在常见的 lisp 中,你如何在抛出错误但未被捕获的地方重新启动?

In common lisp how do you restart where the error was thrown not caught?

这个问题其实是我对重启的理解不够

cl-json 的编码器中有一个诱人的宏,我想使用

with-substitute-printed-representation-restart

但是我不太明白是怎么回事。

这个

(cl-json::encode-json-plist (list :boo "boo" :foo "foo"))

returns

{"boo":"boo","foo":"foo"}

这个

(cl-json::encode-json-plist (list :boo "boo" :foo  (lambda (a b) (+ a b))))

发出不可编码值错误信号

我想从 cl-json 找到函数并拥有它的那一点重新开始 return 当它遇到我在列表中添加的 lambda 时,我选择了一些东西。

(defun my-func ()
 (handler-bind ((cl-json::UNENCODABLE-VALUE-ERROR 
                #'(lambda (e) (invoke-restart 'return-default))))
   (myencode (list :boo "boo" :foo (lambda (a b) (+ a b))))
 )
)

(defun myencode (alist)
 (restart-case
  (cl-json::encode-json-plist-to-string alist)
  (return-default () :report "Just return a default could not do this string" "barf")
 )
)

returns "barf"

我想要它 return

{"boo":"boo","foo":"barf"}

我该如何使用那个宏来做这个? 换句话说,我希望在抛出错误的地方而不是在捕获错误的地方重新启动。我可以这样做吗?

我不明白文档是否有误,或者我是否在错误地阅读代码,但是只要无法对对象进行编码,就应该已经可以重新启动。如果您如下重新定义了 cl-json encode-json 的默认方法,那么您需要重新启动。

(defmethod encode-json (anything &optional (stream *json-output*))
  "If OBJECT is not handled by any specialized encoder signal an error
which the user can correct by choosing to encode the string which is
the printed representation of the OBJECT."
  (with-substitute-printed-representation-restart (anything stream)
    (unencodable-value-error anything 'encode-json)))

顺便说一句,您可以重新定义以便重新启动接受一个参数,即要打印的字符串:

(defmethod encode-json (anything &optional (stream *json-output*))
  "If OBJECT is not handled by any specialized encoder signal an error
which the user can correct by choosing to encode the string which is
the printed representation of the OBJECT."
  (with-substitute-printed-representation-restart (anything stream)
    (restart-case (unencodable-value-error anything 'encode-json)
      (use-value (v)
        :report "Use a different encoding"
        (check-type v string)
        (write v :stream stream :escape t)))))

例如:

CL-USER> (handler-bind
                ((json:unencodable-value-error
                  (lambda (err)
                    (declare (ignore err))
                    (invoke-restart 'use-value "UNKNOWN"))))
              (json:encode-json
               `(((foo . ,#'print) (bar . "baz")))))
[{"foo":"UNKNOWN","bar":"baz"}]

您可能想直接询问库的作者