2.3符号化的数据

2.3符号化的数据
我们所使用的所有的复合的数据对象最终都是由数字组成的。
在这一部分中,我们通过引入符号数据的能力来扩展我们的语言
的表现力。

        2.3.1 引用
如果我们能用符号来形成复合的数据,我们能有如下的列表
(a b c d)
(23 45 17)
((Norah 12) (Molly 9) (Lauren 6) (Charlotte 4))

能够包含符号的列表看起来像我们的语言中的表达式。
(* (+ 23 45) (+ x 9)
(define (fact n) (if (= n 1) 1 (* n (fact (-n 1)))))

为了操作符号,在语言中,我们需要一种新的元素,对数据对象的引用的能力。
假定我们要组装一个列表(A B)。我们不能使用(list a b)来完成,因为
这个表达式组装了一个由a,b的值组成的列表,而不是a,b 这两个符号本身。
在自然语言的上下文中,这是个很有名的问题,单词与句子可能被作为语义
实体或者是语法实体而存在。在自然语言中的做法是使用引用符号来彰显
一个单词或者是一个句子认定为语法实体,也就是字符常量。例如 “张三”的
第一个字是“张” 如果我们告诉某人,说你的名字。我们期望听到他的名字。
但是如果我们对某人说“说‘名字’这两个字”。我们期望听到的是“名字”这两个字。
注意到的是我们要描述某人可能说的内容时,我们就被迫使用级联的引号来标识。

为了标识列表与符号应该作为数据对象来对待而不是作为被解释的表达式,我们能够遵循
同样的做法。然而,我们为了引用的格式符号不同于自然语言,我们传统使用的一个单引号
仅在被引用对象的开头。在SCHEME的语法中我们能够这么做,因为我们依赖空格和括号分隔
对象。因此,单个引号符号的含义就是引用接下来的对象。

现在我们能够区分符号和它们的值:
(define a 1)
(define b 2)

(list a b)
(1 2)

(list 'a 'b)
(a b)

(list 'a b)
(a 2)
引用也允许我们对复合的对象进行操作.对于列表也使用传统的方式表示
(car '(a b c))
a

(cdr '(a b c))
(b c)

与此保持一致的是,我们在执行 '() 时得到了空值。表示为NIL。

在操作符号的时候,我们使用的另一个原子方法是 eq?  ,它有
两个符号作为输入参数值,然后测试它们是否相等。 使用eq?,
我们能实现一个有用的程序叫做memq. 这个程序有两个参数,一个是符号,
另一个是列表。如果符号不在列表中,返回假,否是返回符号首次出现
的元素到最后一个元素的子列表。

(define (memq item x)
 (cond
          ((null? x) false)
            ((eq? item (car x)) x)
          (else (memq item (cdr x)))
))

例如如下的程序
(memq 'apple '(pear banana prune))
值是假。

如下的程序
(memq 'apple '(x (apple sauce) y apple pear))
值是 (apple pear)

练习2.53
在执行以下的表达后,解释器返回的值是什么?
(list  'a 'b 'c)

(list (list 'george))
(cdr '((x1 x2) (y1 y2)))

(cadr '((x1 x2) (y1 y2)))
(pair? (car '(a short list)))
(memq 'red '((red shoes) (blue socks)))

(memq 'red '(red shoes blue socks))


练习2.54
两个列表的判断相等性的程序是 equal? 判断的条件是对应顺序的
元素都相等.如下所示:

(equal?   '(this is a list) '(this is a list))
是真,但是如下的表达式
(equal?   '(this is a list) '(this (is a) list))
是假.为了更精确的,我们能够递归地定义equal? 用基础的eq?和equal?
eq?用户判断两个符号的相等性,equal?用来判断两个列表的相等性。
即列表的头部等于头部,尾部等于尾部。
使用这个思想,实现这个程序。

练习2.55 解释如下的表达式的执行结果。
(car ''abracadabra) 的执行结果是后一个引号。

猜你喜欢

转载自blog.csdn.net/gggwfn1982/article/details/81458635