3.8 序对与列表
序对将两个任意值联结到一起。过程 cons 用于构造序对, 过程 car 和 cdr 分别用于提取序对中的第一个和第二个元素。 谓语 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 引述形式的元素时,其打印结果就会使用 list 或 cons。例如,用 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* 来缩写:
函数 write 和 display 会将序对或列表打印为不带前导 '、cons、list 或 list* 的形式。对于序对或列表来说,write 和 display 除了是否会应用于列表中的元素外并无任何区别:
> (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 Reference的Pairs and Lists一节中提供了关于序对与列表的更多信息。
与传统的 Lisp 不同,Racket 中的序对是不可变的,pair? 和 list? 也只会识别不可变的序对和列表。过程 mcons 用于创建 可变序对, 它可与 set-mcar! 和 set-mcdr!,以及 mcar 和 mcdr 协同工作。可变序对使用 mcons 打印,而 write 和 display 会将可变序对打印为带有 { 和 } 的形式:
> (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 Reference的Mutable Pairs and Lists一节中提供了关于可变序对的更多信息。