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

Common lisp defmethod和defun的Common Lisp特殊变量范围不同?,common-lisp,scope,Common Lisp,Scope,要么我遗漏了一些非常愚蠢的东西,要么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 &

要么我遗漏了一些非常愚蠢的东西,要么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 >
    
    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 >
    
    (定义ttprint对象(前缀输出)
    (格式化为“~A:in-defun:<~A>~%”前缀*打印可读*)
    (let((*可阅读打印*t))
    (格式t“let:calling defun:<~A>~%”*打印可读*)
    (ttprint对象“来自let”t))
    let:调用defun:
    从let:in defun:
    
  • With let defmethod的工作方式与defun不同,因此意外:

    (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 >
    
    (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 >
    
    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 >
    
    (defclass empty())
    (defmethod打印对象((自空)输出)
    (格式化为“in-defmethod:<~A>~%”*以可读方式打印*)
    (ttprint对象“从defmethod”输出)
    (let((*可阅读打印*t))
    (ttprint对象“from let”t)
    (格式t“let:调用defmethod:<~A>~%”*以可读方式打印*)
    (格式t“let:~A”(使实例为空)
    从let:in defun:
    let:调用defmethod:
    let:在def方法中:
    来自defun中的defmethod:
    
  • 同样,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 >
    
    (progn)
    (setq*打印可读性*t)
    (ttprint object“from setf”t)
    (格式t“setf:calling defmethod:<~A>~%”*以可读方式打印*)
    (格式t“setf:~A”(使实例为空)
    从setf:在defun:
    setf:调用defmethod:
    setf:在defmethod中:
    来自defun中的defmethod:
    
  • 希望是我


    提前感谢,Frank

    ~A
    将*可读打印*绑定为false(添加强调):

    arg(任何对象)打印时不带转义字符(如princ)。如果arg是字符串,则其字符将逐字输出。如果arg为nil,则打印为nil;冒号修饰符(~:A)将导致将参数nil打印为(),但如果参数是复合结构,例如列表或向量,则包含的任何nil事件仍将打印为nil

    ~A
    *打印转义*
    绑定为false,将
    *可读打印*
    绑定为false。

    当你这样做的时候

    (format t "let: ~A" (make-instance 'empty))
    
    ~A
    指令将
    *print readable*
    绑定为false(即
    nil
    ),最后Lisp编写器调用对象的
    print object
    方法。如果不需要此绑定,可以尝试不修改打印机变量的
    ~W

    参数(任何对象)按照每个打印机控件打印 变量(如通过写入)。此外,~W与深度正确交互 缩写,不将深度计数器重置为零~W不是 接受参数。如果给定冒号修饰符,~W绑定
    *将pretty*
    打印为true。如果给定at符号修饰符,~W将
    *打印级别*
    *打印长度*
    绑定为零

    ~W为检测圆度和圆度提供自动支持 分享。如果
    *打印圆*
    的值不是零并且应用了~W 对于循环(或共享)引用的参数 在输出中插入适当的#n#标记,而不是打印 争论

    如果使用
    ~W
    ,则会得到您最初期望的结果:

    (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 >
    
    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 >
    
    CL-USER>(let((*可读打印*t))
    (ttprint对象“from let”t)
    (格式t“let:调用defmethod:<~A>~%”*以可读方式打印*)
    (格式t“let:~w”(使实例为空)
    从let:in defun:
    let:调用defmethod:
    let:in defmethod:
    来自defun中的defmethod:
    
    D'oh-谈论“最小惊喜”,特别是因为defmethod和defun的结果不同。非常感谢您快速详尽的回答,非常欢迎!不过,这并不是
    defmethod
    defun
    之间的区别;这是因为
    ~a
    *print readable*
    绑定为false,对于对象,
    ~a
    调用相应的
    print object
    方法。唯一令人惊讶的是
    format
    绑定了一个值并导致调用另一个方法,在这种情况下,该方法依赖于
    format
    绑定的值。