common-lisp - defmethod 和 defun 的 Common Lisp 特殊变量范围不同?

标签 common-lisp scope

要么是我遗漏了一些非常愚蠢的东西,要么是 defmethod 和 defun 的特殊变量范围出乎意料地不同(使用 SBCL 1.1.14 测试):

  1. 如预期的那样:

    (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 >
    
  2. 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 >
    
  3. 还有 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/

相关文章:

java - 将变量范围从一帧扩展到另一帧

angular - 在 Angular 8 中获取组件外部的引用变量

AngularJS:指令范围没有被调用 $destroy

clojure - 在我自己的数据结构中递增数字时 clojure 中的不变性,从常见的 lisp 可变性到 clojure 不变性

lisp - 使用 html5-parser 和 xmls Common Lisp 浏览网页

lambda - 如何将 lambda 传递给宏?

Delphi - 当单元名称与属性名称相同时如何解决冲突?

java - Java 中 main 内变量的作用域?

lisp - 有办法保存 Common Lisp 或 Scheme 的 REPL 状态吗?

tree - LISP 编程 - 计算树节点的函数