我正在教自己Common Lisp。我一直在看康威生命游戏的一个例子,有一段我不理解的语法。
完整的代码可用here。特别是我遇到麻烦的部分如下:
(defstruct (world (:constructor %make-world))
current
next)
(defun make-world (width height)
(flet ((make-plane (width height)
(make-array (list width height)
:element-type 'bit
:initial-element 0)))
(%make-world
:current (make-plane width height)
:next (make-plane width height))))
我想知道,首先,%make-world中百分号的意义是什么?其次,为什么构造函数指定了两个不同的名称? (make-world和%make-world)我之前看过这个语法,但名字总是一样的。似乎有一些更深层的功能,但它正在逃避我。
答案 0 :(得分:6)
有关标识符的Lisp世界有几种命名约定。有关概述,请参阅:http://www.cliki.net/Naming+conventions
使用系统生成的函数可以完成对象或结构。 DEFSTRUCT
将创建一个MAKE-FOO
函数,其中插槽的init值为关键字参数。
有时人们更喜欢具有正常位置参数的函数 - 写入时间较短,并且在调用函数时必须给出参数 - 您不能省略它们。
在这种情况下,需要以这样的方式命名DEFSTRUCT
生成的函数,使其不与用户应该使用的名称冲突。所以%MAKE-FOO
表示它是库的内部辅助函数,预计不会被用户级代码调用。
答案 1 :(得分:5)
My Lisp有点生疏,但我相信它是这样的:
%符号没有特殊含义。我已经看到它用于内部函数(例如由labels
定义),但没有什么会阻止你正常调用它。如果查看defstruct文档,您会看到(:constructor %make-world)
定义了一个命名构造函数%make-world
(默认情况下,构造函数将被称为make-world
。这个构造函数可用于创建world
结构,使用命名参数初始化字段。
函数make-world
的存在使得创建这些结构更容易。问题是,current
和next
应该是二维数组,但是如果不是将这些数组传递给构造函数,而是可以只说出维度是什么,函数会创建什么,那么它会更方便那些数组适合你。这正是make-world
所做的。它首先定义了一个内部函数make-plane
,它可以创建一个数组,然后使用它创建2个数组并将它们传递给构造函数%make-plane
。
与%
字符的通常用法一致(同样,这只是一个约定),它告诉您,作为希望使用world
结构的程序员,您不应该使用%make-world
构造函数,而是make-world
函数。