
- 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)