LISP - 结构体类型
Lisp - 使用 defstruct 定义结构类型
Section titled “Lisp - 使用 defstruct 定义结构类型”在 Common Lisp 中,defstruct 是一个宏,用于定义简单、高效、类似记录的数据结构。它提供了一种便捷的方式,将相关数据分组到具有命名槽位(named slots)的单个对象中。defstruct 会自动为您的新数据类型生成构造函数、访问器和其他实用函数。
定义基本结构
Section titled “定义基本结构”最简单的 defstruct 定义了一种新类型及其槽位。Lisp 随后会创建一套用于操作该类型的函数。
示例:一个 book 结构
Section titled “示例:一个 book 结构”main.lisp
Section titled “main.lisp”;; 定义一个名为 'book' 的结构,包含四个槽位。(defstruct book title author subject id)
;; 创建 'book' 结构的一个实例。;; 构造函数 'make-book' 会自动为我们创建。;; 使用关键字参数是标准且易读的做法。(let ((book1 (make-book :title "The Pragmatic Programmer" :author "Andy Hunt & Dave Thomas" :subject "Software Engineering" :id 9780201616224)))
;; 使用自动生成的访问器访问槽位。 ;; 访问器格式是 '结构名'-'槽位名'。 (print (book-title book1)) (print (book-author book1)) (print (book-id book1))
;; 类型谓词 'book-p' 也已创建。 (print (book-p book1)))"The Pragmatic Programmer""Andy Hunt & Dave Thomas"9780201616224Tdefstruct 的特性和选项
Section titled “defstruct 的特性和选项”defstruct 具有高度可定制性。您可以为槽位定义默认值,并控制辅助函数的生成。
示例:带默认值的槽位
Section titled “示例:带默认值的槽位”(defstruct user (name "Anonymous") ; 'name' 槽位的默认值 (level 1) ; 'level' 的默认值 email)
;; 创建一个用户,只提供必需的 'email' 槽位。(let ((new-user (make-user :email "guest@example.com"))) (print (user-name new-user)) ; 打印默认值 (print (user-level new-user)))
;; 创建另一个用户,覆盖默认值。(let ((admin-user (make-user :name "Admin" :level 99 :email "admin@example.com"))) (print (user-name admin-user)))"Anonymous"1"Admin"使用 :include 进行结构继承
Section titled “使用 :include 进行结构继承”结构通过 :include 选项支持单一继承。新结构会继承父结构的所有槽位。
(defstruct person name age)
;; 'student' 结构包含 'person',因此继承了它的槽位。(defstruct (student (:include person)) major gpa)
(let ((s1 (make-student :name "Jane Doe" :age 21 :major "Computer Science" :gpa 3.8))) ;; 我们可以使用父结构的访问器。 (print (student-name s1)) (print (student-major s1)))"Jane Doe""Computer Science"defstruct 与 CLOS defclass 的比较
Section titled “defstruct 与 CLOS defclass 的比较”在 defstruct 和 defclass(来自 Common Lisp 对象系统,即 CLOS)之间进行选择是一个常见的设计决策:
- 何时使用
defstruct:当您需要一个简单、轻量级的数据容器时。结构通常由 Lisp 系统更高效地实现,非常适合对性能敏感的代码,或者当您只需将少量数据捆绑在一起时。 - 何时使用
defclass:当您需要面向对象编程的全部功能时。这包括多重继承、方法特化(多态性)和类的动态重新定义等,这些特性在结构中是不可用的。
可以将 defstruct 视为用于“数据对象”,而 defclass 用于“行为对象”。
defstruct 是 Lisp 程序员工具箱中一个实用且必不可少的工具。它提供了一种简单、高效、清晰的方式来定义用于聚合信息的自定义数据类型,在原始列表和功能齐全的 CLOS 之间取得了完美的平衡。