在常见的Lisp中,如何重新启动未引发错误的地方?

问题描述

这个问题确实是因为我对重启不了解。

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

with-substitute-printed-representation-restart

但是a,我不太了解。

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

返回

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

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

发出UNencodable-VALUE-ERROR信号

我想从cl-json找到该函数并返回它的那点重新开始 当我遇到列表中包含的添加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")
 )
)

返回“ barf”

我希望它退回

{"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"}]

您可能想直接问图书馆的作者