;constructor(cons x y) ; creates a new pair p; selectors(car p) ; returns car part of pair(cdr p) ; returns cdr part of pair; mutators(set-car! p new-x) ; changes car pointer in pair(set-cdr! p new-y) ; changes cdr pointer in pair; Pair, anytype -> undef ; side-effect only
(define a (list12))(define b a); a ==> (1 2); b ==> (1 2)(set-car! a 10); a ==> (10 2); b ==> (10 2)
由于 a 和 b 指向同一块内存,修改 a 的同时,也会修改 b,如下图所示:
![](/assets/Screen Shot 2018-02-26 at 11.28.23 PM.jpg)
因此我们需要在充分了解 mutation 的基础上加以使用。
例2:
如下图所示修改 x 对应的 list:
![](/assets/Screen Shot 2018-02-26 at 11.41.18 PM.jpg)
可以这样实现:
(define x (list 'a 'b))(set-car! (cdr x) (list12))
Equivalence and Identity
在表示相等关系时,我们常常有这样两个问题:
a 和 b 是否很像?
a 和 b 是否是同一个?
如果 a 和 b 很像,那么二者至少表面看起来给人相似的感觉,这就是 equivalence。
如果 a 和 b 是同一个,那么二者实际上指代同一个物体,这就是 identity。
; equivalence; a、b 是否是同一个(eq? a b); identity; a、b 是否长得像(equal? a b)
例1:Stack Data Abstraction
Stack 数据抽象的几个组成部分如下所示:
; constructor(make-stack) ; returns an empty stack; selectors(top stack) ; returns current top element from a stack; operations(insert stack elt) ; returns a new stack with the element added to the top of the stack(delete stack) ; returns a new stack with the top element removed from the stack(empty-stack? stack) ; returns #t if no elements, #f otherwise; contract; if s is a stack, created by (make-stack) and subsequent stack procedures, where i is the; number of insertions and j is the number of deletions, then; 1. if j > i : then it is an error; 2. if j = i : then (empty-stack? s) is true, and (top s) and (delete s) are errors; 3. if j < i : then (empty-stack? s) is false and (top (delete (insert s val))) = (top s); 4. if j <= i: then (top (insert s val)) = val for any val.
; constructor(make-queue) returns an empty queue; selectors(front-queue q) returns the object at the front of the queue. If queue is empty signals error; mutators(insert-queue q elt) returns a queue with elt at the rear of the queue(delete-queue q) returns a queue with the item at the front of the queue removed; operations/predicators(empty-queue? q) tests if the queue is empty; (queue? q) tests if the object is a queue; contracts; if q is a queue, created by (make-queue) and subsequent queue procedures, where i is the number; of insertions, j is the number of deletions, and x_i is the i-th item inserted into q, then; 1. if j > i: then it is an error; 2. if j = i: then (empty-queue? q) is true, and (front-queue q) and (delete-queue q) are errors; 3. if j < i: then (front-queue q) = x_(j+1)