在defun和defstruct中的百分号符号

10

我正在自学Common Lisp。我一直在看康威生命游戏的一个例子,但有一部分语法我不理解。

完整代码可以在这里找到。我特别困扰的部分如下:

(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个回答

9
在Lisp世界中,有几种命名约定用于标识符。详见: http://www.cliki.net/Naming+conventions 通过使用系统生成的函数,可以创建对象或结构。 DEFSTRUCT 将创建一个带有关键字参数的 MAKE-FOO 函数,其中包含槽的初始值。
有时人们更喜欢使用带有正常的 位置 参数的函数——这样写更短,并且在调用该函数时必须提供参数——不能省略它们。
在这种情况下,有必要以不与用户应使用的名称发生冲突的方式为 DEFSTRUCT 生成的函数命名。因此,%MAKE-FOO 表示这是库的内部帮助程序函数,并且预计用户级别代码不会调用它。

8

我的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函数。


1
这很有帮助;我读了两个答案才明白,现在一切都清楚了。 - Joshua Kast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接