而结构可以想成是,这些函数通通都替你定义好了的向量。

    要想定义结构,使用 defstruct 。在最简单的情况下,只要给出结构及字段的名字便可以了:

    1. (defstruct point
    2. x
    3. y)

    这里定义了一个 point 结构,具有两个字段 xy 。同时隐式地定义了 make-pointpoint-pcopy-pointpoint-xpoint-y 函数。

    每一个 make-point 的调用,会返回一个新的 point 。可以通过给予对应的关键字参数,来指定单一字段的值:

    1. #S(POINT X 0 Y 0)

    存取 point 字段的函数不仅被定义成可取出数值,也可以搭配 setf 一起使用。

    定义结构也定义了以结构为名的类型。每个点的类型层级会是,类型 point ,接着是类型 structure ,再来是类型 atom ,最后是 t 类型。所以使用 point-p 来测试某个东西是不是一个点时,也可以使用通用性的函数,像是 typep 来测试。

    1. > (point-p p)
    2. T
    3. T
    1. (defstruct polemic
    2. (type (progn
    3. (format t "What kind of polemic was it? ")
    4. (effect nil))

    如果 make-polemic 调用没有给字段指定初始值,则字段会被设成缺省表达式的值:

    结构显示的方式也可以控制,以及结构自动产生的存取函数的字首。以下是做了前述两件事的 point 定义:

    1. (defstruct (point (:conc-name p)
    2. (x 0)
    3. (y 0))
    4. (defun print-point (p stream depth)
    5. (format stream "#<~A, ~A>" (px p) (py p)))

    :conc-name 关键字参数指定了要放在字段前面的名字,并用这个名字来生成存取函数。预设是 point- ;现在变成只有 p 。不使用缺省的方式使代码的可读性些微降低了,只有在需要常常用到这些存取函数时,你才会想取个短点的名字。

    函数 print-point 会用缩写的形式来显示点:

    1. #<0,0>