重新定义conses的print-object方法在不同的CL实现中有不同的效果

Redefinition of the print-object method for conses has different effects in different CL implementations

尝试不以标准列表表示法打印 conses,但总是以点对的形式打印,我以最小的努力重新定义了方法 print-object

(defmethod print-object((c cons) str)
  (format str "(~a . ~a)" (car c) (cdr c)))

但是不同的实现效果是不一样的

在 Clozure CL 和 LispWorks Personal 中,结果如我所料:

CL-USER 1 > (defmethod print-object((c cons) str)
                (format str "(~a . ~a)" (car c) (cdr c)))
#<STANDARD-METHOD PRINT-OBJECT NIL (CONS . (T . NIL)) 200A45AB>

CL-USER 2 > '(a b c )
(A . (B . (C . NIL)))

而在 SBCL 和 AllegroCLexpress 中,列表的打印方式没有任何变化:

* (defmethod print-object((c cons) str)
     (format str "(~a . ~a)" (car c) (cdr c)))

#<STANDARD-METHOD PRINT-OBJECT (CONS T) {10051EBC53}>
* '(a b c)

(A B C)

所以,我想知道这是否是由于语言规范中的一些歧义,如果这种行为被明确声明为未指定,是否是由于 REPL 与包的某种交互,或者,最后,如果有关于此定义的正确实现和其他不正确的实现。最后一点,在 SLIME 中给出这样的定义会导致 SLIME 本身的彻底破坏!

有人可以阐明这些差异,并建议一种替代方法(如果存在的话),问题较小,以获得我的 objective?

标题有点误导。 SBCL 没有 print-object conses 方法。所以你不能重新定义它。出于某种原因,它允许您定义这样的方法,但它的打印机不会调用它。

AFAIK,SBCL 不支持 built-in 类型的 user-defined print-object 方法。它们不被打印机调用。如果您查看打印机源,它正在使用 TYPE-CASE 结构,为不同的数据类型调用各种打印函数。

您可以在 SBCL 中为 CLOS 类 定义 print-object 方法,它们将被调用。

这与 ANSI CL 不兼容吗?或许。至少不提供print-object方法的部分应该是不兼容的。这仍然不意味着可以改变它们...

根据 PRINT-OBJECT 方法定义 all/most/many 类(包括 builtin-classes)的打印是否有用。是的

CLHS 11.1.2.1.2 列出了更改通用 lisp 包中内容的限制条件——这似乎 运行 与情况 19 不一致。

Except where explicitly allowed, the consequences are undefined if any of the following actions are performed on an external symbol of the COMMON-LISP package:

...

  1. Defining a method for a standardized generic function which is applicable when all of the arguments are direct instances of standardized classes.

部分解决方法,仅当 *print-pretty* 为非零时,将使用 pretty print dispatch table.

;(in-package cl-user)
(set-pprint-dispatch 'cons (lambda (s obj) (format s "(~A . ~A)" (car obj) (cdr obj))))
NIL
;(in-package cl-user)
(let ((*print-pretty* t)) (print (list 1 2 3)))

(1 . (2 . (3 . NIL)))
(1 2 3)
;(in-package cl-user)