如何理解:普通lisp的defstruct中的print-function

时间:2014-03-04 05:13:53

标签: common-lisp

我正在读这本书成功的lisp,有一个例子:

(defstruct (ship
              (:print-function
               (lambda (struct stream depth)
                 (declare (ignore depth))
                 (format stream "[ship ~A of ~A at (~D, ~D) moving (~D, ~D)]"
                         (ship-name struct)
                         (ship-player struct)
                         (ship-x-pos struct)
                         (ship-y-pos struct)
                         (ship-x-vel struct)
                         (ship-y-vel struct)))))
    (name "unnamed")
    player
    (x-pos 0.0)
    (y-pos 0.0)
    (x-vel 0.0)
    (y-vel 0.0))

我如何理解这一部分:

(lambda (struct stream depth)
                     (declare (ignore depth))

为什么声明忽略深度?我觉得很困惑,为什么不把lambda写为

(lambda (struct stream)
         .....)

由于

2 个答案:

答案 0 :(得分:5)

你不能简单地忽略Common Lisp中的参数 - 例如,javascript。也就是说,如果你写一个像

这样的函数
(defun foo (bar baz)
  (list bar baz))

你不能用任何其他数量的参数调用它:

(foo 'a 'b)     ; correct number of arguments
=> (a b)
(foo 'a)        ; too few arguments
=> error
(foo 'a 'b 'c)  ; too many arguments
=> error

由于使用三个参数(对象,流和深度)调用打印机功能,因此还必须使用三个参数定义所有打印机。声明只是通过向编译器指示您故意不使用参数来删除警告消息。

答案 1 :(得分:4)

Common Lisp标准说明了这一点:

  

如果使用:print-function选项,那么当结构类型为   结构名称是打印的,指定的打印机功能是   呼吁三个论点:

     
      
  • 要打印的结构(结构名称的通用实例)。
  •   
  • 要打印到的流。
  •   
  • 表示当前深度的整数。该整数的大小可以在不同之间变化   实现;但是,它可以可靠地进行比较   *print-level*确定深度缩写是否合适。
  •   

所以它是一个三参数函数。我们需要编写一个函数,然后接受三个参数。

像往常一样,如果我们的代码不使用所有参数,我们可以声明它们被忽略,这样编译器就不会打印警告。此处用户未使用变量depth

示例:在以下函数中,我们不清楚是否忘记使用b,或者是否故意使用它。

CL-USER 21 > (defun foo (a b)
               (list a))
FOO

CL-USER 22 > (compile 'foo)
;;;*** Warning in FOO: B is bound but not referenced
FOO

现在我们可以告诉编译器我们选择不使用b

CL-USER 23 > (defun foo (a b)
               (declare (ignore b))
               (list a))
FOO

编译期间没有警告:

CL-USER 24 > (compile 'foo)
FOO
NIL
NIL