PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now:...

69
PPL Pairs, lists and data abstraction

Transcript of PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now:...

Page 1: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

PPL

Pairs, lists and data abstraction

Page 2: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Compound Data

• Until now: atomic, unrelated entities• Now: organized into structures• Why?– Better conceptual level of design– Modularity– Maintenance– Code reuse

• Actually a new type in the signature

Page 3: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Data Abstractions in Scheme?

• Of course, but first we need to present 2 new data types in Scheme:– Pairs– Lists

Page 4: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pairs

• Combines two data entities into a single unit• Scheme provides built in primitives:– Value constructor: cons– Selectors: car, cdr– Identify predicate: pair?– Equality: equal?

Page 5: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pairs

> (define x (cons 1 2))> (car x)1> (cdr x)2> x(1 . 2)

“toString” of pair

Page 6: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pairs

Each data entity can be anything!> (define y (cons x (quote a)))> (car y)(1 . 2)> (cdr y)'a> y((1 . 2) . a)

Recall that x is the pair (cons 1 2)

Page 7: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pairs

Do not confuse (cons 1 2) with (1 . 2) !!

1st is a Scheme expression (syntax) and 2nd is the ‘toString’ of the value (same as lambda and procedure)

Page 8: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pair Type

Type constructor: PairType of:• cons: [T1*T2 -> Pair(T1,T2)]

• car: [Pair(T1,T2) -> T1]

• cdr: [Pair(T1,T2) -> T2]

Page 9: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Church Numbers

• Defined recursively:– Zero is a Church number.– For a Church number c, S(c) is a Church number

• Symbolic representation of natural numbers:– Zero, S(Zero), S(S(Zero)),…

• So what does it have to do with us?– We can represent them using pairs!– Zero, (S.Zero), (S.(S.Zero)), …

Page 10: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Church Numbers using Recursive Pairs

;; Type: [Number -> Church-num](define church-num (λ (n) (if (zero? n) 'Zero (cons 'S (church-num (- n 1))))))

> (church-num 3)'(S S S . Zero)

;(cons ‘S (cons ‘S (cons ‘S ‘Zero))))

Page 11: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Church Numbers using Recursive Pairs

;; Type: Church-num -> Number(define church-val (λ (c-n) (if (eq? c-n 'Zero) 0 (+ 1 (church-val (cdr c-n))))))

Page 12: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Useful Example(define member (lambda (el pair) (cond ((and (member-type-test el (car pair)) (member el (car pair))) #t) ((eq? el (car pair)) #t) ((and (member-type-test el (cdr pair)) (member el (cdr pair))) #t) ((eq? el (cdr pair)) #t) (else #f))))

(define member-type-test (lambda (el pair-candidate) (and (symbol? el) (pair? pair-candidate))))

Page 13: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Lists

• Finite sequence <v1, …, vn> (v1 … vn)

• v1 is head, (v2 … vn) is tail• Value constructors: cons and list– Empty: (list)– Non-empty:• (cons head tail) – tail must be a list!• (list e1 … en)

Page 14: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

List Implementation

• Lists are actually nested pairs!• The inmost item is an empty list• Printing form of list is nice:– ( <a1> <a2> … <an> )

Page 15: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Lists

• Both will create the same list:(list 1 2 3)

(cons 1 (cons 2 (cons 3 (list))))

Page 16: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Lists

• Selectors:– car: head– cdr: tail

• Predicates:– list?– null?– equal?

Page 17: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Examples

> (define one-through-four (list 1 2 3 4))> one-through-four(1 2 3 4)> (car one-through-four)1> (cdr one-through-four)(2 3 4)> (car (cdr one-through-four))2

Page 18: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Note on Pairs and Lists

• Pair and List types have same value constructor and selector

• Scheme can live with it because its dynamically typed

Page 19: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Visual Representation

• Empty list

• Non empty list ((1 2) 3 4):

3

1 2

4

Page 20: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Lists and Types

• Homogenous– Examples: (1 2 3), ((1 2) (3)) – LIST(Number), LIST(T), …

• Heterogeneous– Examples: (1 #f 3), ((1 2) 3)– LIST

Page 21: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Useful List Operations

car + cdr:> (define x

(list 5 6 8 2))

> (car x)5> (cdr x)(6 8 2)

> (car (cdr x))6> (cadr x)6> (cddr x)(8 2)

Page 22: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Selector: list-ref

nth element of a list:;; Type: [LIST * Number -> T](define list-ref (λ (l n) (if (= n 0) (car l) (list-ref (cdr l) (- n 1)))))

(define squares (list 1 4 9 16 25 36))

(list-ref squares 4)

Page 23: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Operator: length

(define length (λ (l) (if (null? l) 0 (+ 1 (length (cdr l))))))

(define squares (list 1 4 9 16 25 36))

(length squares)6

Page 24: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Iterative length

(define length (λ (l) (letrec ((iter (λ (l c) (if (null? l) c (iter (cdr l) (+ c 1)))))) (iter l 0))))

Page 25: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Operator: append

(define append (λ (l1 l2) (if (null? l1) l2 (cons (car l1) (append (cdr l1) l2)))))

(append (list 1 2 3) (list 3 4))

Page 26: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Iterative append ;; Type: [LIST * LIST -> LIST](define append (λ (l1 l2) (letrec ((iter (λ (l1 l2 c) (if (null? l1) (c l2) (iter (cdr l1) l2 (λ (app-cdr-l1) (c (cons (car l1) app-cdr-l1)))))))) (iter l1 l2 (lambda (x) x)))))

Page 27: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Constructor make-list

Builds a list of given with given values(define make-list (λ (l v) (if (= l 0) (list) (cons v (make-list (- l 1) v)))))

Page 28: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Using Lists to Represent Trees

• Unlabeled trees:– Empty tree ()– Leaf is just value– Non-empty tree – non-empty list

• Example: (1 (2 3)) is the tree:

Page 29: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Using Lists to Represent Trees

• How can we add data to non-leaf nodes? (i.e. labeled tree) : each node is also a list!

• ((1) ((2) (3)))• Now we can create labeled trees:• (1 (0) (3 (2) (4)))

Page 30: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Leaves Count

• Unlabeled tree(define count-leaves (λ (t) (cond ((null? t) 0) ((not (list? t)) 1) (else (+ (count-leaves (car t)) (count-leaves (cdr t)))))))

Page 31: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Type Correctness with Pairs and Lists

• cons and list are primitives (not special forms!)

• So we need more axioms.

Page 32: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pairs

For every type environment _Tenv and type expressions _S,_S1,_S2:

Tenv |- cons:[S1*S2 -> PAIR(S1,S2)]

Tenv |- car:[PAIR(S1,S2) -> S1]

Tenv |- cdr:[PAIR(S1,S2) -> S2]

Tenv |- pair?:[S -> Boolean]Tenv |- equal?:[PAIR(S1,S2)*PAIR(S3,S4) -> Boolean]

Page 33: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Homogenous Lists

For every type environment Tenv and type expression S:Tenv |- list:[Empty -> LIST(S)]Tenv |- list:[S* ...*S -> LIST(S)] n >0Tenv |- cons:[S*LIST(S) -> LIST(S)]Tenv |- car:[LIST(S) -> S]Tenv |- cdr:[LIST(S) -> LIST(S)]Tenv |- null?:[LIST(S) -> Boolean]Tenv |- list?:[S -> Boolean]Tenv |- equal?:[LIST(S)*LIST(S) -> Boolean]

Page 34: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Heterogeneous Lists

For every type environment Tenv and type expression S:Tenv |- list:[Empty -> LIST]Tenv |- cons:[S*LIST -> LIST]Tenv |- car:[LIST -> S]Tenv |- cdr:[LIST -> LIST]Tenv |- null?:[LIST -> Boolean]Tenv |- list?:[S -> Boolean]Tenv |- equal?:[LIST*LIST -> Boolean]

Page 35: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Type Derivation Example(define first-first (λ (p) (car (car p))))

1. {p:T1} |- p: T1

2. { } |- car : [Pair(T2,T3) -> T2

3. {p: Pair(T2,T3)} |- (car p):T2

4. { } |- car : [Pair(T21,T31) -> T21

5. {p: Pair(T22,T32)} |- (car p):T22

7. {p: Pair(Pair(T21,T31),T32)} |- (car (car p)): T21

8. {} |- (λ (p)…): [Pair(Pair(T21,T31),T32) -> T21]

9. { } |- first-first : [Pair(Pair(T21,T31),T32) -> T21]

Page 36: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

What About Data Abstraction (ADT)?

• An interface: separation between usage (client) and implementation (supplier)

• Supplier gives constructors and selectors (getters), and client uses them.

• Order of development:1. Client level2. Supplier level

Page 37: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

ADT

• It’s a new type with a difference: type is semantic while ADT is syntactic

• Signature of constructor• Signature of operators• Rules of correctness (Invariants)

Page 38: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

So Why Start with Pairs and Lists?

• Pairs and lists will be our implementation! The client will not know we used pairs and lists, she will just use the operations we give her!

• Example next slide

Page 39: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Constructors

Signature: make-binary-tree(l,r)Purpose: Returns a binary tree whose left

sub-tree is l and whose right sub-tree is rType: [Binary-Tree*Binary-Tree -> Binary-

Tree]Pre-condition: binary-tree?(l) and binary-

tree?(r)

Signature: make-leaf(d)Purpose: Returns a leaf binary-tree whose

data element is dType: [T -> Binary-Tree]

Page 40: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: SelectorsSignature: left-tree(r), right-tree(r)Purpose: (left-tree <t>): Returns the left sub-tree

of the binary-tree <t>.(right-tree <t>): Returns the right sub-tree of the

binary-tree <t>.Type: [Binary-Tree -> Binary-Tree]Pre-condition: composite-binary-tree?(t)

Signature: leaf-data(r)Purpose: Returns the data element of the leaf

binary-tree <t>.Type: [Binary-Tree -> T]Pre-condition: leaf?(t)

Page 41: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: PredicatesSignature: leaf?(t)Type: [T -> Boolean]Post-condition: true if t is a leaf -- constructed by make-leaf

Signature: composite-binary-tree?(t)Type: [T -> Boolean]Post-condition: true if t is a composite binary-tree --

constructed bymake-binary-tree

Signature: binary-tree?(t)Type: [T -> Boolean]Post-condition: result = (leaf?(t) or composite-binary-tree?(t) )

Signature: equal-binary-tree?(t1, t2)Type: [Binary-Tree*Binary-Tree -> Boolean]

Page 42: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Invariants

leaf-data(make-leaf(d)) = dleft-tree(make-binary-tree(l,r)) = lright-tree(make-binary-tree(l,r)) = rleaf?(make-leaf(d)) = trueleaf?(make-binary-tree(l,r)) = falsecomposite-binary-tree?(make-binary-tree(l,r)) = true

composite-binary-tree?(make-leaf(d)) = false

Page 43: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Client Level

;Signature: count-leaves(tree);Purpose: Count the number of leaves of ’tree’;Type: [binary-Tree -> number](define count-leaves (lambda (tree) (if (composite-binary-tree? tree) (+ (count-leaves (left-tree tree)) (count-leaves (right-tree tree))) 1)))

Page 44: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Client Level

• More examples in lecture notes.• Look at them.• Really, look at them.

Page 45: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Implementation (supplier)

;Signature: make-binary-tree(l,r)

;Type: [T1*T2 -> LIST]

;Pre-condition: binary-tree?(l) ; and binary-tree?(r)(define make-binary-tree (lambda (l r) (list l r)))

;Signature: make-leaf(d);Type: [T -> T](define make-leaf (lambda (d) d))

;Signature: left-tree(t);Type: [LIST -> T];Pre-condition: composite-

binary-tree?(t)(define left-tree (lambda (t) (car t)))

;Signature: right-tree(t);Type: [LIST -> T];Pre-condition: composite-

binary-tree?(t)(define right-tree (lambda (t) (cadr t)))

Page 46: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Implementation;Signarture: leaf-data(t);Type: [T -> T];Pre-condition: leaf?(t)(define leaf-data (lambda (t) t))

;Signarture: leaf?(t);Type: [T -> Boolean](define leaf? (lambda (t) #t))

;Signarture: composite-binary-tree?(t);Type: [T -> Boolean](define composite-binary-tree? (lambda (t) (and (list? t) (list? (cdr t)) (null? (cddr t)) (binary-tree? (left-tree t)) (binary-tree? (right-tree t)))

Page 47: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Implementation;Signarture: binary-

tree(t);Type: [T -> Boolean](define binary-tree? (lambda (t) (or (leaf t) (composite-b-t t))))

;Signature: equal-binary-tree?(t1,t2);Type: [T1*T2 -> Boolean];Pre-condition: binary-tree?(t1) and

binary-tree?(t2)(define equal-binary-tree? (λ (t1 t2) (cond ((and (composite-binary-tree? t1) (composite-binary-tree? t2)) (and (equal-binary-tree? (left-tree t1) (left-tree t2)) (equal-binary-tree? (right-tree t1) (right-tree t2)))) ((and (leaf? t1) (leaf? t2)) (equal? (leaf-data t1) (leaf-data t2))) (else #f))))

Page 48: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Invariants

Seems ok, but look:> (leaf? (make-leaf (list 5 6)))#t> (has-leaf? (list 5 6) (make-leaf (list 5 6)))#f

We have no way to distinct composite leaves from tree…

We need a better implementation: tagged-data!

Page 49: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Tagged Data ADTSignature: attach-tag(x,tag)Purpose: Construct a tagged-

data valueType: [T*Symbol -> Tagged-

data(T)]

Signature: get-tag(tagged)Purpose: Select the tag from a

tagged-data valueType: [Tagged-data(T) ->

Symbol]

Signature: get-content(tagged)Purpose: Select the data from a

tagged-data valueType: [Tagged-data(T) -> T]

Signature: tagged-data?(datum)

Purpose: Identify tagged-data values

Type: [T -> Boolean]

Signature: tagged-by? (tagged,tag)

Purpose: Identify tagged-data values

Type: [T*Symbol -> Boolean]

Page 50: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Binary Tree ADT: Implementation using Tagged-Data

;Signature: make-binary-tree(l,r);Type: [(LIST union T1)*(LIST

union T2) ; -> Tagged-data(LIST)];Pre-condition: binary-tree?(l) ; and binary-tree?(r)(define make-binary-tree (lambda (l r) (attach-tag (list l r) ’composite-binary-tree)))

;Signature: make-leaf(d);Type: [T -> Tagged-data(T)](define make-leaf (lambda (d) (attach-tag d ’leaf)))

;Signature: left-tree(t);Type: [Tagged-data(LIST) ; -> Tagged-data(LIST union

T)];Pre-condition: composite-binary-

tree?(t)(define left-tree (lambda (t) (car (get-content t))))

;Signature: right-tree(t);Type: [Tagged-data(LIST) ->

Tagged-data(LIST union T)];Pre-condition: composite-binary-

tree?(t)(define right-tree (lambda (t) (cadr (get-content t))))

Page 51: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Proving Invariants

Invariant: leaf-data(make-leaf (d)) = d:For expression d, eval[(leaf-data (make-leaf d))] = eval[d]eval[(leaf-data (make-leaf d))] ==>eval[(leaf-data (attach-tag eval[d] ’leaf))] ==>eval[(get-content (attach-tag eval[d] ’leaf))] ==>eval[d]

Page 52: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Tagged-Data Implementation

• Have you noticed that we didn’t implement the tagged-data ADT?

• That’s the whole idea! We are clients! We don’t have to know the implementation!

• But we’ll give it anyway…

Page 53: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Tagged-Data ADT Implementation;Signature: attach-tag(x,tag);Type: [Symbol*T -> PAIR(Symbol, T)](define attach-tag (λ (x tag) (cons tag x)))

;Signature: get-tag(tagged);Type: PAIR(Symbol,T) -> Symbol(define get-tag (λ (tagged) (car tagged)))

;Signature: get-content(tagged);Type: [PAIR(Symbol,T) -> T](define get-content (λ (tagged) (cdr tagged)))

;Signature: tagged-data?(datum);Type: [T -> Boolean](define tagged-data? (λ (datum) (and (pair? datum) (symbol? (car datum)))))

;Signature: tagged-by?(tagged,tag);Type: [T*Symbol -> Boolean](define tagged-by? (λ (tagged tag) (and (tagged-data? tagged) (eq? (get-tag tagged) tag))))

Page 54: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Type Inference with Type Constraints using ADT

• ADT:– Type expression (TE)– Substitution– Equation

• Client produces– sub-application, sub-combination

– Infer-type, solve

• Implementation– TE is tagged-data (tag is

type constructor)– Substitution is 2-element

list– Equation is 2-element

list

Page 55: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Type Inference with Type Constraints using ADT

• Full implementation in course site.• We describe part of it.

Page 56: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Type Expression ADT (partial)Constructors:Signature: make-proc-te(tuple-te, te)Type: Client view: [Tuple*Type -> Procedure]Example: (make-proc-te (make-tuple-te (list Number)) 'Number)==> (-> (*Number) Number)

Signature: make-tuple-te(te-list)Type: Client view:[LIST(TE)-> Tuple]Example: (make-tuple-te(list 'Number (make-proc-te (make-tuple-te (list 'Number))'T1)))==> (* Number (-> (* Number) T1))

Some getters:Signature: get-constructor(te)Type: Client view: [Composite-Type-Expression -> Symbol]Example: (get-constructor (make-tuple-te (list 'Number 'Number))) ==> *

Signature: tuple-components(te)Type: Client view: [Tuple -> List(TE)]Example: (tuple-components (make-tuple-te (list 'Number 'Number))) ==> (Number Number)

Signature: proc-return-te(te)Type: Client view:[Procedure -> TE]Example: (proc-return-te (make-proc-te (make-tuple-te (list 'Number)) 'T1)) ==> T1Some predicates:

Signature: equal-atomic-te?(te1 te2)Type: [LIST union Symbol * LIST union Symbol -> Boolean]Signature: type-expr?(te)Type: [T -> Boolean]

Page 57: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Procedures as Data

• So far we’ve seen only pairs and lists as compound data

• Procedures can be data too! And in more than one way

• What?! Procedures can be data?! Yes.

Page 58: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pair ADT

• Suppose Scheme did not include the built-in Pair or List type

• Pair ADT– Define the ADT (cons’r, getters, etc)– Implement it using procedures(!!)

Page 59: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pair ADT: Cons’r, Getters, Predicates…

Signature: cons(x,y)Type: [T1*T2 -> PAIR(T1,T2)]

Signature: car(p)Type: [PAIR(T1,T2) -> T1]

Signature: cdr(p)Type: [PAIR(T1,T2) -> T2]

Signature: pair?(p)Type: [T -> Boolean]

Signature: equal-pair?(p1,p2)Type: [PAIR(T1,T2)*PAIR(T1,T2) -> Boolean]

Page 60: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pair ADT: Invariants

(car (cons x y)) = x(cdr (cons x y)) = y

Page 61: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pair ADT Implementation I: Eager (also called message passing)

;Signature: cons(x,y);Type: [T1*T2 -> [Symbol -> (T1 union T2)](define cons (λ (x y) (λ (m) (cond ((eq? m 'car) x) ((eq? m 'cdr) y) (else (error "..." m) )))))

Not to confuse with

applicative-eval!

Page 62: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pair ADT Implementation I: Eager

;Signature: car(pair);Type: [[Symbol -> (T1 union T2)] -> T1](define car (λ (pair) (pair ’car)))

;Signature: cdr(pair);Type: [[Symbol -> (T1 union T2)] -> T2](define cdr (λ (pair) (pair ’cdr)))

Page 63: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

What Just Happened?

• A pair is a procedure that stores the information about the pair components

• The “magic”:– The substitution: the values are “planted” in the

procedure– The returned value is a procedure that is not

applied. car and cdr apply it.

Page 64: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

applicative-eval[ (cons 1 2) ] ==>*<closure (m)

(cond ((eq? m ’car) 1)((eq? m ’cdr) 2)(else (error “…" m) ))>

Page 65: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

applicative-eval[ (car (cons 1 2 )) ] ==>applicative-eval[ car ] ==> <closure (pair) (pair ’car)>applicative-eval[ (cons 1 2) ] ==>* <the cons closure>

sub[pair, <cons closure>, (pair ’car) ] ==> (<cons closure> ’car)

reduce:( (lambda (m)

(cond ((eq? m ’car) 1)((eq? m ’cdr) 2)

(else (error "Argument not ’car or ’cdr -- CONS" m) )))’car) ==>*applicative-eval, sub, reduce:

(cond ((eq? ’car ’car) 1)((eq? ’car ’cdr) 2)(else (error “…" ’car) )) ==>

1

Page 66: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pair ADT Implementation II: Lazy

Lazy;Signature: cons(x,y);Type: [T1*T2 ; -> [ [T1*T2 -> T3] -> T3]](define cons (lambda (x y) (lambda (sel) (sel x y))))

Eager;Signature: cons(x,y);Type: [T1*T2 -> [Symbol -> (T1

union T2)](define cons (λ (x y) (λ (m) (cond ((eq? m 'car) x) ((eq? m 'cdr) y) (else (error "..." m))))))

Page 67: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Pair ADT Implementation II: Lazy;Signature: cons(x,y);Type: [T1*T2 -> [ [T1*T2 ; -> T3] -> T3]](define cons (lambda (x y) (lambda (sel) (sel x y))))

;Signature: car(pair);Type: [[ [T1*T2 -> T3] -> T3] -> T1](define car (lambda (pair) (pair (lambda (x y) x))))

;Signature: cdr(pair);Type: [[ [T1*T2 -> T3] ; -> T3] -> T2](define cdr (lambda (pair) (pair (lambda (x y) y))))

Page 68: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

applicative-eval[ (cons 1 2) ] ==><closure (sel) (sel 1 2)>

applicative-eval[ (car (cons 1 2 )) ] ==>* applicative-eval[ car ] ==> <closure (pair) (pair (lambda(x y) x))> applicative-eval[ (cons 1 2) ] ==>* <closure (sel) (sel 1 2) >sub, reduce:applicative-eval[ ( <closure (sel) (sel 1 2) > (lambda(x y) x) ) ] ==>*applicative-eval[ ( (lambda(x y) x) 1 2) ] ==>applicative-eval, sub, reduce:1

Page 69: PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.

Eager vs Lazy

Eager• More work at constructions

time. Immediate at selection time.

• Selectors that are not simple getters can have any arity.

Lazy• Immediate at construction

time. More work at selection time.

• Selectors can be added freely, but must have the same arity.