我正在读这本书成功的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)
.....)
由于
答案 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