什么是印读一致性?

What is print-read consistency?

在定义 print-object 方法时它有多重要?

例如,在我看来,SBCL 中的 hash-table 个实例违反了这一原则。

Print-read 一致性表示,在 CL 中,如果 *print-readably* 为真,则打印对象应该:

  • 生成打印表示,当使用有效的标准可读表读取时,它与对象相似
  • 或发出类型为 print-not-readable 的错误信号。

相似性 的定义稍微复杂一些,因为它不一定能在单个图像中定义,因为它的全部目的是允许打印对象,然后再读取在另一张图片中。它在3.2.4.2 of the spec, although all of 3.2.4中的定义值得一读。特别注意允许实现扩展相似性的定义。

请注意,我上面的定义中存在一些缺陷:特别是我认为其他打印​​机和 reader 控制变量需要具有 *print-readably* 的标准值才有意义(例如 *package**read-default-float-format*等等。with-standard-io-syntax这里是你想要的工具。

最后请注意,在某些情况下,相似性是针对同一实现 的多个图像定义的。对于标准未定义其可读打印表示的对象,允许实现打印内容,以便 自身 的另一个实例可以重建类似的对象:它不必确保其他实现可以。

这意味着如果您要定义一种打印对象的机制,那么如果 *print-readably* 为真,它应该以读取类似对象的方式打印对象 (也许在同一个实现中),或者发出适当的错误信号:它应该 而不是 做的是以一种不可读的方式悄悄地打印对象,或者以一种读取表示不会 return 一个相似的对象。这样做的一个好方法是使用 print-unreadable-object,其全部目的是为您确保这一点。

散列表可能可打印也可能不可读。在 SBCL 中,它们是:

* (defvar *h* (make-hash-table))
*h*
* (setf (gethash 'foo *h*) 1)
1
* *h*
#<hash-table :TEST eql :COUNT 1 {1002CE5863}>
* (with-standard-io-syntax (print *h*))

#.(SB-IMPL::%STUFF-HASH-TABLE (MAKE-HASH-TABLE) (QUOTE ((FOO . 1)))) 
#<hash-table :TEST eql :COUNT 1 {1002CE5863}>

#.(...) 形式将在 SBCL 中读取时重新创建一个类似的哈希表(但仅在 SBCL 中)。

在另一个实现 (Clozure CL) 中,哈希表不可读地打印:

? (defvar *h* (make-hash-table))
*h*
? (setf (gethash 'foo *h*) 1)
1
? *h*
#<hash-table :test eql size 1/60 #x3020012A119D>
? (with-standard-io-syntax (print *h*))

> Error: Attempt to print object #<HASH-TABLE :TEST EQL size 1/60 #x3020012A119D> on stream #<SYNONYM-STREAM to *TERMINAL-IO* #x302000B9DC1D>