3.8 序对与列表

序对将两个任意值联结到一起。过程 cons 用于构造序对, 过程 carcdr 分别用于提取序对中的第一个和第二个元素。 谓语 pair? 用于识别序对。

一些序对的打印形式即为:元素本身的打印形式用括号括住,前面有个 ', 元素之间有个 .

例如:
> (cons 1 2)

'(1 . 2)

> (cons (cons 1 2) 3)

'((1 . 2) . 3)

> (car (cons 1 2))

1

> (cdr (cons 1 2))

2

> (pair? (cons 1 2))

#t

列表是将序对组合在一起的链表。确切来说,列表要么是空表 null, 要么就是第一个元素为列表元素,第二元素为列表的序对。谓语 list? 用于识别列表。谓语 null? 用于识别空表。

列表通常打印为 ' 后跟用一对括号括住的列表元素。

例如:
> null

'()

> (cons 0 (cons 1 (cons 2 null)))

'(0 1 2)

> (list? null)

#t

> (list? (cons 1 (cons 2 null)))

#t

> (list? (cons 1 2))

#f

当列表或序对中存在无法写成 quote 引述形式的元素时,其打印结果就会使用 listcons。例如,用 srcloc 构造的值无法写成 quote 引述的形式,因此它会使用 srcloc 来打印:

> (srcloc "file.rkt" 1 0 1 (+ 4 4))

(srcloc "file.rkt" 1 0 1 8)

> (list 'here (srcloc "file.rkt" 1 0 1 8) 'there)

(list 'here (srcloc "file.rkt" 1 0 1 8) 'there)

> (cons 1 (srcloc "file.rkt" 1 0 1 8))

(cons 1 (srcloc "file.rkt" 1 0 1 8))

> (cons 1 (cons 2 (srcloc "file.rkt" 1 0 1 8)))

(list* 1 2 (srcloc "file.rkt" 1 0 1 8))

另见 list*

如最后一例所示,无法用 list 缩写的一系列 cons 会用 list* 来缩写:

函数 writedisplay 会将序对或列表打印为不带前导 'conslistlist* 的形式。对于序对或列表来说,writedisplay 除了是否会应用于列表中的元素外并无任何区别:

例如:
> (write (cons 1 2))

(1 . 2)

> (display (cons 1 2))

(1 . 2)

> (write null)

()

> (display null)

()

> (write (list 1 2 "3"))

(1 2 "3")

> (display (list 1 2 "3"))

(1 2 3)

列表上的最重要的预定义过程都会对列表中的元素进行迭代:

> (map (lambda (i) (/ 1 i))
       '(1 2 3))

'(1 1/2 1/3)

> (andmap (lambda (i) (i . < . 3))
         '(1 2 3))

#f

> (ormap (lambda (i) (i . < . 3))
         '(1 2 3))

#t

> (filter (lambda (i) (i . < . 3))
          '(1 2 3))

'(1 2)

> (foldl (lambda (v i) (+ v i))
         10
         '(1 2 3))

16

> (for-each (lambda (i) (display i))
            '(1 2 3))

123

> (member "Keys"
          '("Florida" "Keys" "U.S.A."))

'("Keys" "U.S.A.")

> (assoc 'where
         '((when "3:30") (where "Florida") (who "Mickey")))

'(where "Florida")

+The Racket ReferencePairs and Lists一节中提供了关于序对与列表的更多信息。

与传统的 Lisp 不同,Racket 中的序对是不可变的,pair?list? 也只会识别不可变的序对和列表。过程 mcons 用于创建 可变序对, 它可与 set-mcar!set-mcdr!,以及 mcarmcdr 协同工作。可变序对使用 mcons 打印,而 writedisplay 会将可变序对打印为带有 {} 的形式:

例如:
> (define p (mcons 1 2))
> p

(mcons 1 2)

> (pair? p)

#f

> (mpair? p)

#t

> (set-mcar! p 0)
> p

(mcons 0 2)

> (write p)

{0 . 2}

+The Racket ReferenceMutable Pairs and Lists一节中提供了关于可变序对的更多信息。