跳至內容

Scheme 程式設計/列表操作

來自華夏公益教科書
Scheme 程式設計
 ← 進一步數學 列表操作 向量操作 → 

列表是 Scheme 中的基本資料結構,就像許多其他函數語言程式設計語言一樣。雖然它們是最簡單的結構之一,但它們擁有豐富的操作集和驚人的多種用途。在本節中,我們將介紹建立和使用列表的基礎知識。

Scheme 列表

[編輯 | 編輯原始碼]

列表是元素序列,以 () 結尾,有時稱為“空列表”或“nil”。我們可以使用 cons 構建列表,它將新元素附加到列表的頭部。

> '()     ; The empty list must be quoted.
()
> (cons 3 '())
(3)
> (cons 2 (cons 3 '()))
(2 3)
> (cons #t (cons 2 (cons 3 '())))
(#t 2 3)

cons 的第一個引數可以是任何 Scheme 物件,第二個引數是列表;(cons x xs) 的值是一個新列表,它包含 x 後跟 xs 中的元素。[1](Scheme 列印列表的方式使用簡寫,隱藏了最後的 ()。在上面的響應中,我們只看到括號內的列表元素。)重要的是要注意,我們必須始終引用 (),以防止 Scheme 嘗試將它解釋為(無效)表示式。

兩個謂詞定義了 Scheme 列表型別。null?()(空列表)為真,其他情況為假,而 pair? 僅對使用 cons 構建的物件返回真。[2]

有兩個基本的函式用於訪問列表的元素。第一個是 car,它提取列表的第一個元素。

> (car (cons 1 '()))
1
> (car (cons 2 (cons 3 '())))
2
> (car '())
; Error!

car 應用於空列表會導致錯誤。

第二個函式 cdr 給我們提供了列表的尾部:即沒有前導元素的列表。

> (cdr (cons 1 '()))
()
> (cdr (cons 2 (cons 3 '())))
(3)
> (cdr '())
; Error!

car 一樣,嘗試將 cdr 應用於空列表會導致錯誤。

三個函式 conscarcdr 滿足一些有用的恆等式。對於任何 Scheme 物件 x 和列表 xs,我們有

(car (cons x xs)) = x
(cdr (cons x xs)) = xs

對於任何非空列表 ys,我們也有

(cons (car ys) (cdr ys)) = ys

顯然,透過連續的 cons 操作構建列表很笨拙。Scheme 提供了內建函式 list,它返回其引數的列表。

> (list 1 2 3 4)
(1 2 3 4)
> (cons 1 (cons 2 (cons 3 (cons 4 '()))))  ; equivalent, but tedious
(1 2 3 4)

list 可以接受任意數量的引數。

我們可以使用 conscarcdr 編寫一系列有用的函式。例如,我們可以定義一個函式來計算列表的長度。

(define (length xs)
  (if (null? xs)
      0
      (+ 1 (length (cdr xs)))))

這個定義,就像大多數列表操作的定義一樣,緊密地遵循列表的遞迴結構。有一個空列表的情況(被分配長度 0),還有一個非空列表的情況(列表尾部的長度加一)。在實踐中,Scheme 提供了 length 作為內建函式。

這是一個簡單的例子。

(define (find-number n xs)
  (if (null? xs)
      #f
      (if (= n (car xs))
          #t
          (find-number n (cdr xs)))))

find-number 如果引數 n 出現在列表 xs 中,則返回 #t,否則返回 #f。再次,這個定義遵循列表引數的結構。空列表沒有元素,所以 (find-number n '()) 總是為假。如果 xs 非空,那麼 n 可以是第一個元素,也可以是在尾部的某個地方。在前一種情況下,find-number 立即返回真。在後一種情況下,返回值應該是 n 是否出現在 (cdr xs) 中,如果是則為真,否則為假。但由於這是 find-number 本身的定義,我們有一個新的引數 (cdr xs) 的遞迴呼叫。

  1. 這是一個簡化的說明,對我們目前的目的來說是正確的。事實上,cons 構建其引數的,它們都可以是任意的 Scheme 物件。第二個元素為 () 或另一個對的對稱為列表;所有其他對稱為不當列表。
  2. Scheme 列表型別的定義比數字、布林值等的定義更寬鬆。雖然 (scheme list) 庫提供了真正的 list? 函式,但此函式是根據 null?pair? 定義的。參見前一條說明。
華夏公益教科書