Common Lisp 中结构的 :print-function 和 *print-readably* 之间的干扰?

问题描述 投票:0回答:1

我正在尝试将一个通用的 lisp 结构可读地打印到一个文件中,以便以后可以读回。看起来 SBCL 有一些相当复杂的内置工具,用于可读地打印复杂对象,这可能避免必须编写专门的打印对象方法。

我的结构自己的

:print-function
是否有可能干扰
*print-readably*

(defstruct (problem-state (:conc-name problem-state.) (:print-function print-problem-state) (:copier nil))
  "A planning state including the current propositional database."
  (name nil :type symbol)  ;last action executed
  (instantiations nil :type list)  ;from last action effect
  (happenings nil :type list)  ;a list of (object (next-index next-time next-direction)) pairs
  (time 0.0 :type real)
  (value 0.0 :type real)
  (heuristic 0.0 :type real)
  (idb (make-hash-table) :type hash-table)  ;integer hash table of propositions
  (hidb (make-hash-table) :type hash-table))  ;integer table for happening events

执行时

(defun save (object file)
  "Saves an object to a file so it can be read in later."
  (with-open-file (out-stream file :direction :output)
    (let ((*print-readably* t))
      (pprint object out-stream))))

对于结构实例,结果是人类可读的,但不是 lisp 可读的。

我是否需要以某种方式禁用

:print-function
(如果这是问题所在)?

data-structures common-lisp hashtable sbcl writefile
1个回答
0
投票

如果您为

:print-function
提供
:print-object
defstruct
选项,那么您指定的打印机将用于打印该类的对象。 正确处理打印机控制变量是该函数的责任。 特别是这意味着如果
*print-readably*
为真,它必须以可读方式打印对象,或者如果它不愿意或不能这样做则发出错误信号:它不应该简单地打印出不可读的东西,更不应该绑定或分配给
*print-readably*
或类似的东西。

print-unreadable-object
可以帮助您纠正这种行为:

(defstruct (foo
            (:print-function (lambda (f s d)
                               (declare (ignore d))
                               (print-unreadable-object (f s :type t :identity t)
                                 ...))))
  ...)

将正确运行,因为

print-unreadable-object
被定义为在
*print-readably*
为真时发出适当的错误信号。

如果您希望能够在需要时可读地打印结构,但在其他情况下则不可读,则使用

:print-function
:print-object
机制相对难以做到这一点。您的功能显然不正确:我怀疑很少有人这样做。

幸运的是有一个简单的答案,就是不使用这些选项,而是在

print-object
上定义方法:

(defstruct foo
  x)

(defmethod print-object ((f foo) s)
  (if *print-readably*
      (call-next-method)
    (print-unreadable-object (f s :type t :identity t)
      (format s "x = ~A" (foo-x f)))))

现在

> *print-readably*
nil

> (let ((*print-readably* t))
    (print (make-foo)))

#S(foo :x nil) 
#<foo x = nil 8010058923>

当然,所有

:print-function
:print-object
机制所做的就是为您在
print-object
上定义程式化方法。来自
defstruct

:print-function
:print-object
选项指定应为结构名称类型的结构生成
print-object
方法。

在 CLOS 之前(当

:print-object
不存在时)
:print-function
以更神奇的方式做了一些事情,但这一切都被 CLOS 大大简化了。

© www.soinside.com 2019 - 2024. All rights reserved.