要么是我遗漏了一些非常愚蠢的东西,要么是 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 >
let 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 >
希望是我...
提前致谢,弗兰克
最佳答案
~A
将 *print-readably*
绑定(bind)到 false(添加了强调):
22.3.4.1 Tilde A: Aesthetic
An arg, any object, is printed without escape characters (as by princ). If arg is a string, its characters will be output verbatim. If arg is nil it will be printed as nil; the colon modifier (~:A) will cause an arg of nil to be printed as (), but if arg is a composite structure, such as a list or vector, any contained occurrences of nil will still be printed as nil.
…
~A
binds*print-escape*
to false, and*print-readably*
to false.
当你这样做的时候
(format t "let: ~A" (make-instance 'empty))
~A
指令将 *print-readably*
绑定(bind)到 false(即 nil
),最终 Lisp 编写器调用 print-object
对象的方法。如果你不想要这个绑定(bind),你可以尝试 ~W
不修改打印机变量:
22.3.4.3 Tilde W: Write
An argument, any object, is printed obeying every printer control variable (as by write). In addition, ~W interacts correctly with depth abbreviation, by not resetting the depth counter to zero. ~W does not accept parameters. If given the colon modifier, ~W binds
*print-pretty*
to true. If given the at-sign modifier, ~W binds*print-level*
and*print-length*
to nil.~W provides automatic support for the detection of circularity and sharing. If the value of
*print-circle*
is not nil and ~W is applied to an argument that is a circular (or shared) reference, an appropriate #n# marker is inserted in the output instead of printing the argument.
如果你使用~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 >
关于common-lisp - defmethod 和 defun 的 Common Lisp 特殊变量范围不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21415891/