- LISP 教程
- LISP - 首页
- LISP - 概述
- LISP - 环境
- LISP - 程序结构
- LISP - 基本语法
- LISP - 数据类型
- LISP - 宏
- LISP - 变量
- LISP - 常量
- LISP - 运算符
- LISP - 决策
- LISP - 循环
- LISP - 函数
- LISP - 谓词
- LISP - 数字
- LISP - 字符
- LISP - 数组
- LISP - 字符串
- LISP - 序列
- LISP - 列表
- LISP - 符号
- LISP - 向量
- LISP - 集合
- LISP - 树
- LISP - 哈希表
- LISP - 输入与输出
- LISP - 文件 I/O
- LISP - 结构体
- LISP - 包
- LISP - 错误处理
- LISP - CLOS
- LISP 有用资源
- Lisp - 快速指南
- Lisp - 有用资源
- Lisp - 讨论
Lisp - 列表
列表一直是传统 LISP 中最重要和主要的复合数据结构。如今的 Common LISP 提供了其他数据结构,如向量、哈希表、类或结构体。
列表是单向链表。在 LISP 中,列表被构建为一个名为 **cons** 的简单记录结构的链,这些结构链接在一起。
Cons 记录结构
**cons** 是一种记录结构,包含两个称为 **car** 和 **cdr** 的组件。
Cons 单元或 cons 是对象,是使用函数 **cons** 创建的一对值。
**cons** 函数接受两个参数并返回一个新的 cons 单元,其中包含这两个值。这些值可以是任何类型对象的引用。
如果第二个值不是 nil 或另一个 cons 单元,则这些值将打印为括号括起来的一对点。
cons 单元中的两个值分别称为 **car** 和 **cdr**。**car** 函数用于访问第一个值,**cdr** 函数用于访问第二个值。
示例
创建一个名为 main.lisp 的新源代码文件,并在其中输入以下代码。
main.lisp
; create and print a cons of car 1, cdr 2 (write (cons 1 2)) ; terminate printing (terpri) ; create and print a cons of car a, cdr b (write (cons 'a 'b)) ; terminate printing (terpri) ; create and print a cons of car 1, cdr nil (write (cons 1 nil)) ; terminate printing (terpri) ; create and print a cons of car 1, cdr as another cons (write (cons 1 (cons 2 nil))) ; terminate printing (terpri) ; create and print multiple cons (write (cons 1 (cons 2 (cons 3 nil)))) ; terminate printing (terpri) ; create and print multiple cons (write (cons 'a (cons 'b (cons 'c nil)))) ; terminate printing (terpri) ; create and print multiple cons (write ( car (cons 'a (cons 'b (cons 'c nil))))) ; terminate printing (terpri) ; create and print multiple cons (write ( cdr (cons 'a (cons 'b (cons 'c nil)))))
输出
执行代码时,它将返回以下结果:
(1 . 2) (A . B) (1) (1 2) (1 2 3) (A B C) A (B C)
上面的示例显示了如何使用 cons 结构来创建单向链表,例如,列表 (A B C) 由三个通过它们的 cdr 链接在一起的 cons 单元组成。
LISP 中的列表
虽然可以使用 cons 单元创建列表,但是构建一个由嵌套的 **cons** 函数调用组成的列表可能不是最佳解决方案。**list** 函数更常用于在 LISP 中创建列表。
list 函数可以接受任意数量的参数,并且因为它是一个函数,所以它会评估其参数。
**first** 和 **rest** 函数分别给出列表的第一个元素和其余部分。以下示例演示了这些概念。
示例
更新名为 main.lisp 的源代码文件,并在其中输入以下代码。
main.lisp
; create and print a list (write (list 1 2)) ; terminate printing (terpri) ; create and print a list (write (list 'a 'b)) ; terminate printing (terpri) ; create and print a list (write (list 1 nil)) ; terminate printing (terpri) ; create and print a list (write (list 1 2 3)) ; terminate printing (terpri) ; create and print a list (write (list 'a 'b 'c)) ; terminate printing (terpri) ; create and print a list an car (write (list 3 4 'a (car '(b . c)) (* 4 -2))) ; terminate printing (terpri) ; create and print a list of lists (write (list (list 'a 'b) (list 'c 'd 'e)))
输出
执行代码时,它将返回以下结果:
(1 2) (A B) (1 NIL) (1 2 3) (A B C) (3 4 A B -8) ((A B) (C D E))
示例
更新名为 main.lisp 的源代码文件,并在其中输入以下代码。
main.lisp
; define a function to return the list (defun my-library (title author rating availability) (list :title title :author author :rating rating :availabilty availability) ) ; call the function and print the result (write (getf (my-library "Hunger Game" "Collins" 9 t) :title))
输出
执行代码时,它将返回以下结果:
"Hunger Game"
列表操作函数
下表提供了一些常用的列表操作函数。
| 序号 | 函数及说明 |
|---|---|
| 1 | car 它接受一个列表作为参数,并返回其第一个元素。 |
| 2 | cdr 它接受一个列表作为参数,并返回一个不包含第一个元素的列表。 |
| 3 | cons 它接受两个参数,一个元素和一个列表,并返回一个在第一个位置插入该元素的列表。 |
| 4 | list 它接受任意数量的参数,并返回一个以这些参数作为列表成员元素的列表。 |
| 5 | append 它将两个或多个列表合并成一个。 |
| 6 | last 它接受一个列表并返回一个包含最后一个元素的列表。 |
| 7 | member 它接受两个参数,其中第二个参数必须是一个列表,如果第一个参数是第二个参数的成员,则它返回从第一个参数开始的列表的其余部分。 |
| 8 | reverse 它接受一个列表并返回一个元素顺序相反的列表。 |
请注意,所有序列函数都适用于列表。
示例
更新名为 main.lisp 的源代码文件,并在其中输入以下代码。
main.lisp
; create a car of a sequence (write (car '(a b c d e f))) ; terminate printing (terpri) ; create a cdr of a sequence (write (cdr '(a b c d e f))) ; terminate printing (terpri) ; create a cons (write (cons 'a '(b c))) ; terminate printing (terpri) ; create a list of lists (write (list 'a '(b c) '(e f))) ; terminate printing (terpri) ; create a list by appending lists (write (append '(b c) '(e f) '(p q) '() '(g))) ; terminate printing (terpri) ; get last car (write (last '(a b c d (e f)))) ; terminate printing (terpri) ; get reverse of the list (write (reverse '(a b c d (e f))))
输出
执行代码时,它将返回以下结果:
A (B C D E F) (A B C) (A (B C) (E F)) (B C E F P Q G) ((E F)) ((E F) D C B A)
car 和 cdr 函数的连接
**car** 和 **cdr** 函数及其组合允许提取列表的任何特定元素/成员。
但是,car 和 cdr 函数的序列可以通过将字母 a(表示 car)和 d(表示 cdr)连接到字母 c 和 r 中来缩写。
例如,我们可以编写 cadadr 来缩写函数调用序列 - car cdr car cdr。
因此,(cadadr '(a (c d) (e f g))) 将返回 d
示例
更新名为 main.lisp 的源代码文件,并在其中输入以下代码。
main.lisp
; create a cons from sequences (write (cadadr '(a (c d) (e f g)))) ; terminate printing (terpri) ; create a cons from a list (write (caar (list (list 'a 'b) 'c))) ; terminate printing (terpri) ; create a cons from a list (write (cadr (list (list 1 2) (list 3 4)))) ; terminate printing (terpri)
输出
执行代码时,它将返回以下结果:
D A (3 4)