百分之登记defun和defstruct

时间:2014-05-05 22:52:16

标签: functional-programming data-structures syntax lisp common-lisp

我正在教自己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)我之前看过这个语法,但名字总是一样的。似乎有一些更深层的功能,但它正在逃避我。

2 个答案:

答案 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的存在使得创建这些结构更容易。问题是,currentnext应该是二维数组,但是如果不是将这些数组传递给构造函数,而是可以只说出维度是什么,函数会创建什么,那么它会更方便那些数组适合你。这正是make-world所做的。它首先定义了一个内部函数make-plane,它可以创建一个数组,然后使用它创建2个数组并将它们传递给构造函数%make-plane

%字符的通常用法一致(同样,这只是一个约定),它告诉您,作为希望使用world结构的程序员,您不应该使用%make-world构造函数,而是make-world函数。