要么我缺少非常愚蠢的东西,要么defmethod和defun的特殊变量范围出乎意料地不同(使用SBCL 1.1.14测试):
正如所料:
(defun ttprint-object (prefix out)
(format out "~A: in defun: < ~A >~%" prefix *print-readably*))
(let ((*print-readably* t))
(format t "let: calling defun: < ~A >~%" *print-readably*)
(ttprint-object "from let" t))
let: calling defun: < T >
from let: in defun: < T >
让defmethod与defun不同,所以出乎意料:
(defclass empty () ())
(defmethod print-object ((self empty) out)
(format out "in defmethod: < ~A >~%" *print-readably*)
(ttprint-object "from defmethod" out))
(let ((*print-readably* t))
(ttprint-object "from let" t)
(format t "let: calling defmethod: < ~A >~%" *print-readably*)
(format t "let: ~A" (make-instance 'empty)))
from let: in defun: < T >
let: calling defmethod: < T >
let: in defmethod: < NIL >
from defmethod: in defun: < NIL >
同样使用setf defmethod的工作方式与defun不同,但与let:
相同(progn
(setq *print-readably* t)
(ttprint-object "from setf" t)
(format t "setf: calling defmethod: < ~A >~%" *print-readably*)
(format t "setf: ~A" (make-instance 'empty)))
from setf: in defun: < T >
setf: calling defmethod: < T >
setf: in defmethod: < NIL >
from defmethod: in defun: < NIL >
希望是我......
先谢谢,弗兰克
答案 0 :(得分:8)
~A
将*print-readably*
绑定为false(强调添加):
22.3.4.1 Tilde A: Aesthetic
arg,任何对象,打印时没有转义字符(如princ)。如果arg是一个字符串,则其字符将逐字输出。如果arg为零,则将打印为零;冒号修饰符(〜:A)将导致nil的arg打印为(),但如果arg是复合结构,例如列表或向量,则任何包含的nil出现仍将打印为nil。
...
~A
将*print-escape*
绑定为false,将*print-readably*
绑定为false。
当你这样做时
(format t "let: ~A" (make-instance 'empty))
~A
指令将*print-readably*
绑定为false(即nil
),最终Lisp编写器调用该对象的print-object
方法。如果您不想要此绑定,可以尝试~W
来修改打印机变量:
22.3.4.3 Tilde W: Write
参数,任何对象,都是按照每个打印机控件打印的 变量(通过写入)。另外,~W与深度正确地相互作用 缩写,通过不将深度计数器重置为零。 ~W没有 接受参数。如果给出结肠修饰符,~W结合
*print-pretty*
为真。如果给出了at-sign修饰符,~W将*print-level*
和*print-length*
绑定为nil。~W为检测圆度和自动提供自动支持 分享。如果
*print-circle*
的值不是nil并且应用了~W 一个循环(或共享)引用的参数,一个 适当的#n#标记插入输出而不是打印 论证。
如果您使用~W
,则会获得您最初预期的结果:
CL-USER> (let ((*print-readably* t))
(ttprint-object "from let" t)
(format t "let: calling defmethod: < ~A >~%" *print-readably*)
(format t "let: ~w" (make-instance 'empty)))
from let: in defun: < T >
let: calling defmethod: < T >
let: in defmethod: < T >
from defmethod: in defun: < T >