要么我缺少一些非常愚蠢的东西,要么特殊变量的范围对于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 >
Run Code Online (Sandbox Code Playgroud)让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 >
Run Code Online (Sandbox Code Playgroud)同样使用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 >
Run Code Online (Sandbox Code Playgroud)希望是我......
先谢谢你,弗兰克
~A绑定*print-readably*到错误(强调添加):
22.3.4.1 Tilde A:美学
arg,任何对象,打印时没有转义字符(如princ).如果arg是一个字符串,则其字符将逐字输出.如果arg为零,则将打印为零; 冒号修饰符(〜:A)将导致nil的arg打印为(),但如果arg是复合结构,例如列表或向量,则任何包含的nil出现仍将打印为nil.
...
~A绑定*print-escape*为假,并且*print-readably*为假.
当你这样做
(format t "let: ~A" (make-instance 'empty))
Run Code Online (Sandbox Code Playgroud)
该~A指令绑定*print-readably*到false(即nil),最终Lisp编写器调用print-object该对象的方法.如果您不想要此绑定,您可以尝试~W不修改打印机变量:
22.3.4.3 Tilde W:写
参数,任何对象,都是按照每个打印机控制变量打印的(如通过写入).此外,~W通过不将深度计数器重置为零来正确地与深度缩写相互作用.~W不接受参数.如果给出冒号修饰符,~W绑定
*print-pretty*为true.如果给出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 >
Run Code Online (Sandbox Code Playgroud)