dav*_*ugh 1 hashtable sbcl common-lisp writefile data-structures
我正在尝试将一个常见的 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
Run Code Online (Sandbox Code Playgroud)
执行时
(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))))
Run Code Online (Sandbox Code Playgroud)
对于结构实例,结果是人类可读的,但不是 Lisp 可读的。
我是否需要以某种方式禁用:print-function(如果这是问题)?
如果您提供: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)
...))))
...)
Run Code Online (Sandbox Code Playgroud)
将表现正确,正如print-unreadable-object定义的那样,如果为 true,则发出适当的错误信号*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)))))
Run Code Online (Sandbox Code Playgroud)
现在
> *print-readably*
nil
> (let ((*print-readably* t))
(print (make-foo)))
#S(foo :x nil)
#<foo x = nil 8010058923>
Run Code Online (Sandbox Code Playgroud)
当然,所有:print-function和:print-object机制所做的就是为您定义风格化的方法print-object。从defstruct:
和
:print-function选项:print-object指定print-object应生成结构名称类型的结构的方法。
在 CLOS 之前(当时:print-object还不存在):print-function以更深刻的神奇方式做了一些事情,但这一切都被 CLOS 大大简化了。