The whole goal of a high-level language is to allow us to suppress unnecessary detail in this manner, while focusing on the use of a procedural abstraction to support some more complex computational design.
pair 抽象是组合两部分数据的好方式,但有时候,我们需要将多部分数据组合在一起,这时候就要借助 list。以下是 list 抽象:
; list 由多个 pair 连接而成,且最后一个元素是 empty list --- 即 ();; Constructor; list: el1, el2, ... -> List<el1, el2, ...>; (list el1 el2 ...) => <L>;; Accessor(define first car) ; first 返回 list 中的第一个元素(define rest cdr) ; rest 返回 list 中剩下的元素组成的 list; first: List<el1, el2...> -> el1; (first <L>) => <el1>; rest: List<el1, el2...> -> List<el2, el3,...>; (rest <L>) => List<el2, el3, ...>;; Predicate; null? anytype -> boolean; (null? <x>) => #f if <x> evaluates to an empty list, else #f
建立数据抽象的目的之一在于这种抽象能使得一些操作变得简便,这些操作通常是数据抽象的第四个组成部分:
;; Operations; Common Pattern #1: cons'ing up a list --- 举例:在区间中生成步长为 1 的 list(define (enumerate-interval from to) (if (> from to)nil (adjoin from (enumerate-interval (+1 from) to)))); Common Pattern #2: cdr'ing down a list --- 举例:找到 list 中的第 n 个元素(define (list-ref lst n) (if (= n 0) (first lst) (list-ref (rest lst) (- n 1)))); Common Pattern #3: cdr'ing and cons'ing --- 举例:复制 list (define (copy list) (if (null? 1st)nil (adjoin (first lst) (copy (rest lst))))); Common Pattern #3: cdr'ing and cons'ing --- 举例:将两个 list 串联(define (append list1 list2) (cond ((null? list1) list2) (else (adjoin (first list1) (append (rest list1) list2)))))