Title: Data directed programming Message passing dottedtail notation
1Lecture 12
Data directed programmingMessage
passingdotted-tail notation applySection 2.4,
pages 169-1872.5.1,2.5.2 pages 187-197(but with
a different example)
2Multiple Representations of Abstract Data
Example geometrical figures
- We develop a package for handling geometrical
figures - Each figure has a unique data representation
- Want to support Generic Operations on figures,
such as - Compute figure area
- Compute figure circumference
- Print figure parameters, etc.
3Geometrical figures interface
Constructors (make-rectangle width
height) (make-circle radius) (make-square
length) Rectangle implementation.. Circle
implementation.. Square implementation.. Gener
ic operations (area figure) (circumference
figure) (fig-display figure)..
We will now see 3 alternative implementations
4Implementation 1 tagged data
- Main idea add a tag (symbol) to every figure
instance - Generic procedures dispatch on parameter type
('circle 2)
('square 1)
('rectangle 1 . 2)
5Attaching tags.
(define (attach-tag type-tag contents) (cons
type-tag contents)) (define (type-tag datum)
(if (pair? datum) (car datum) (error
"Bad tagged datum -- TYPE-TAG" datum))) (define
(contents datum) (if (pair? datum) (cdr
datum) (error "Bad tagged datum --
CONTENTS" datum)))
6Tagged data rectangle implementation
(define (make-rectangle width height)
(attach-tag 'rectangle (cons width
height))) (define (width rect) (car
rect)) (define (height rect) (cdr rect)) (define
(circumference-rect rect) ( 2 ( (width rect)
(height rect)))) (define (area-rect rect) (
(width rect) (height rect)))(define
(fig-display-rect rect) (my-display "Rectangle
width, (width rect) ", height "
(height rect))) assume my-display takes any
number of arguments and prints them.
7Tagged data circle implementation
(define (make-circle radius) (attach-tag
'circle (list radius))) (define PI
3.1415926) (define (radius circle) (car
circle)) (define (circumference-circle circle)
( 2 PI (radius circle))) (define (area-circle
circle) (let ((r (radius circle))) ( PI r
r))) (define (fig-display-circle circle)
(my-display Circle radius, (radius circle)))
8Tagged data generic operations
(define (circumference fig) (cond ((eq?
'rectangle (type-tag fig))
(circumference-rect (contents fig)))
((eq? 'circle (type-tag fig))
(circumference-circle (contents fig) .
.))
(define (area fig) (cond ((eq? 'rectange
(type-tag fig)) (area-rect (contents
fig))) ((eq? 'circle (type-tag fig))
(area-circle (contents fig) .
.))
(define (fig-display fig) (cond ((eq?
'rectange (type-tag fig))
(fig-display-rectangle (contents
fig))) ((eq?
'circle (type-tag fig))
(fig-display-circle (contents fig) .
.))
9The Difficulties
The system is not additive/modular
- The generic procedures must know about all types.
- If we want to add a new type we need to
- add it to each of the operations,
- be careful with name clashes.
(define (area fig) (cond ((eq? 'rectange
(type-tag fig)) (area-rect (contents
fig))) ((eq? 'circle (type-tag fig))
(area-circle (contents fig) .
.))
10Implementation 2 data directed programming
- Main idea work with a table.
- Keep a pointer to the right procedure to call in
the table, keyed by the operation/type combination
11Data-directed programming (Cont)
Assume we have a global two dimensional table
and the following operations on it
Adds val to the table, under keys key1, key2
(put key1 key2 val)
Retrieves the value found in the table under keys
key1, key2 OR f if the value is not found
(get key1 key2) ? val/f
12Rectangle implementation
(define (install-rectangle-package)
Implementation (define (width rect) (car
rect)) (define (height rect) (cdr rect))
(define (circumference rect) ( 2 ( (width
rect) (height rect)))) (define (area rect)
( (width rect) (height rect))) (define
(fig-display rect) (my-display "Rectangle
width , (width rect) , height "
(height rect))) (define (make-rect width
height) (attach-tag 'rectangle (cons width
height))) Interface to the rest of the
system (put 'circumference 'rectangle
circumference) (put 'area 'rectangle area)
(put 'fig-display 'rectangle fig-display) (put
'make-fig 'rectangle make-rect) 'done)
13Circle implementation
(define (install-circle-package)
Implementation (define PI 3.1415926) (define
(radius circle) (car circle)) (define
(circumference circle) ( 2 PI (radius
circle))) (define (area circle) (let ((r
(radius circle)) ( PI r r))) (define
(fig-display circle) (my-display Circle
radius, (radius rect))) (define (make-circle
radius) (attach-tag 'circle (list radius)))
Interface to the rest of the system (put
'circumference 'circle circumference) (put
'area 'circle area) (put 'fig-display 'circle
fig-display) (put 'make-fig 'circle
make-circle) 'done)
14Generic procedures
(define (circumference fig) (apply-generic
'circumference fig))
(define (area fig) (apply-generic 'area fig))
(define (fig-display fig) (apply-generic
'fig-display fig))
- Apply generic
- Locates the right procedure in the table
- Calls it
- Passes the figure-data as a parameter
15Apply-generic
(define (apply-generic op arg) (let ((type
(type-tag arg))) (let ((proc (get op type)))
(if proc (proc (contents arg))
(error "No operation for this
type -- APPLY-GENERIC" op
type-tag)))))
16Summary Data Directed programming
Data Directed programming The data (argument)
triggers the right operation based on the
data type.
- Data Directed programming is more modular
- To add a representation, we only need to write
- a package for the new representation without
- changing generic procedures. (Execute the
install - procedure once).
- Changes are local.
- No name clashes.
-
- install-circle-package
- install-rectangle-package
- ..
17Implementation 3 Message Passing
- Main idea the figure is represented by a
procedure - The procedure dispatches on the operation type
Data Directed Intelligent operations that work
with different data
types.
Message Passing Intelligent data types that
support different
operations.
In message passing the idea is that the data gets
a message that tells it which operation to
invoke, and returns the result.
18Message Passing (cont)
circumference area fig-display
Generic operations
19Message passing style rectangle figure
The constructor has it all.
(define (make-rectangle width height) (lambda
(op) (cond ((eq? op 'area) ( height width))
((eq? op 'circumference) ( 2 ( width
height))) ((eq? op 'fig-display)
(my-display "Rectangle width, width)
height, " height))
(else (error "Unknown op
MAKE-RECTANGLE" op)))))
Another way to write this
(define (make-rectangle width height) (define
(dispatch op) (cond ... as above
))
dispatch)
20Message passing style circle figure
The constructor has it all.
(define (make-circle radius) (define PI
3.1415926) (lambda (op) (cond ((eq? op
'area) ( PI radius radius)) ((eq? op
'circumference) ( 2 PI radius)) ((eq?
op 'fig-display) (my-display
Circle radius radius)) (else
(error "Unknown op MAKE-CIRCLE" op)))))
21Generic operations and new apply-generic
(define (circumference fig) (apply-generic
'circumference fig))
(define (area fig) (apply-generic 'area fig))
(define (fig-display fig) (apply-generic
'make-fig fig))
(define (apply-generic op arg) (arg op))
22Summary Message Passing
- Additive
- Avoids name-clashes problems
- No need for a table
- More difficult to extend for multi-parameter
operations
Message passing is the basis for Object Oriented
Programming and we will discuss it again later.
23Writing procedures with a variable number of
parameters (dotted-tail notation)
All other parameters will be passed in a list
named z
(define (proc x y . z) ltbodygt)
24Dotted-tail notation examples
x ? ? y ? ? z ? ?
1
- (define (proc x y . z) ltbodygt)
- (proc 1 2 3 4 5 6)
2
(3 4 5 6)
null
ERROR
25Dotted-tail notation another example
- (define (proc . z) ltbodygt)
- (proc 1 2 3 4 5 6)
z ? ?
(1 2 3 4 5 6)
null
(1 (2 3))
26Dotted-tail notation another example
We want to implement a procedure (count) that
gets a variable number of parameters and returns
their number
(count 1 7 8 9 1) ? 5 (count 0) ? 1 (count) ? 0
(define (count . s) _________________)
(length s)
27Dotted-tail notation yet another example
(define (lt x . y) (length (filter (lambda (z)
(lt z x)) y)))
What does this procedure do ?
(lt 1 7 8 9 1 0 -1) ? 2 (lt 1000 1 10 0) ? 3 (lt
1) ? 0 (lt) ? ERROR
lt returns the number of parameters that are
smaller than the first parameter.
28The builtin procedure Apply
- Suppose we want to apply some procedure proc
- but the parameters are available as a list
(apply proc lst)
will give the same result as
(proc v1 v2 vn)
assuming lst is (v1 v2 vn)
29Apply examples
(apply (list 1 2 3))
? 6
(apply count (list 1 2 3))
? 3
(apply lt (list 10 1 2 3 11 9))
? 4
? (1 2 3 4)
(apply append '((1) (2) (3) (4)))
(apply expt '(2 4))
? 16
? (1 2 3 4 5)
(apply list '(1 2 3 4 5))
30General map
(define (f x y z) ( x ( 2 y) ( 5
z))) (general-map f '(1 2 3) '(2 3 4) '(2 4 7))
? (15 28 46)
31Another apply example
Exercise Implement a procedure, add-abs, that
receives 0 or more numbers, and returns the sum
of their absolute values.
Examples(add-abs) ? 0 (add-abs 1 -2 -3 4) ? 10
(define (add-abs . l) (if (null? l) 0
( (abs (car l)) _________________________))
)
Does not work!!
(add-abs (cdr l))
32Another apply example
Exercise Implement a procedure, add-abs, that
receives 0 or more numbers, and returns the sum
of their absolute values.
Examples(add-abs) ? 0 (add-abs 1 -2 -3 4) ? 10
(define (add-abs . l) (if (null? l) 0
( (abs (car l)) _________________________))
)
This is ok!
(apply add-abs (cdr l))
33Another apply example (cont)
Exercise Implement a procedure, add-abs, that
receives 0 or more numbers, and returns the sum
of their absolute values.
Another solution (also using apply).
(define (add-abs . l) (apply
________________________))
(map abs l)