220 likes | 395 Views
Lecture 18: Tables and OOP. Pair as OOP Delay and force. *table*. a. 1. 2. 3. 4. b. c. d. One dimentional tables. One dimentional tables. ( define (assoc key records) (cond ((null? records) false) ((equal? key (caar records)) (car records))
E N D
Lecture 18: Tables and OOP Pair as OOP Delay and force
*table* a 1 2 3 4 b c d One dimentional tables
One dimentional tables (define (assoc key records) (cond ((null? records) false) ((equal? key (caar records)) (car records)) (else (assoc key (cdr records))))) (define (lookup key table) (let ((record (assoc key (cdr table)))) (if record (cdr record) false)))
One dimentional tables (define (insert! key value table) (let ((record (assoc key (cdr table)))) (if record (set-cdr! record value) (set-cdr! table (cons (cons key value) (cdr table))))) 'ok) Example: (insert! ‘e 5 table)
a 1 2 3 4 *table* b c d e 5 One dimentional tables (define (insert! key value table) (let ((record (assoc key (cdr table)))) (if record (set-cdr! record value) (set-cdr! table (cons (cons key value) (cdr table))))) 'ok)
*table* One dimentional tables (define (make-table)(list '*table*))
Tables in OO style (define (make-table) (let ((local-table (list '*table*))) (define (lookup key-1 key-2) . . . ) (define (insert! key-1 key-2 value) . . . 'ok) (define (dispatch m) (cond ((eq? m 'lookup-proc) lookup) ((eq? m 'insert-proc!) insert!) (else (error "Unknown operation -- TABLE" m)))) dispatch))
Table in OO style (define operation-table (make-table)) (define get (operation-table 'lookup-proc)) (define put (operation-table 'insert-proc!))
local-table lookup: insert!: E1 dispatch: p: key-1 key-2b: . . . *table* (define oper-table (make-table)) | GE make-table: GE oper-table: p: b: (let ((local-table (list '*table*))) . . . )
Programming Styles – Procedural vs. Object-Oriented • Procedural programming: • Organize system around procedures that operate on data (do-something <data> <arg> ...) (do-another-thing <data>) • Object-based programming: • Organize system around objectsthat receive messages • (<object> 'do-something <arg>) • (<object> 'do-another-thing) • An object encapsulates data and operations • Message passing and procedure are the means to write Object • Oriented code in scheme
Object-Oriented Programming Terminology • Class: • specifies the common behavior of entities • in scheme, a "maker" procedure • E.g. cons or make-table in our previous examples • Instance: • A particular object or entity of a given class • in scheme, an instance is a message-handling procedure made by the maker procedure • E.g. oper-table in our previous examples
delay and force (delay <exp>) ==> a promise to evaluate exp (force <delayed object>) ==> evaluate the delayed object and return the result (define x (delay (+ 1 1))) x #<promise> (force x) 2 (delay <exp>) is a special form. force is not a special form.
What are these mysterious delay and force ? delay is a special form such that (delay <exp>) is equivalent to (lambda () <exp>) force is a procedure that calls a procedure produced by delay: (define (force delayed-object) (delayed-object))
(define x (delay (+ 1 1))) | GE x: GE p: b: (+ 1 1) (force x) | GE (x) | GE 2
Normal (Lazy) order evaluation? Apply operator with unevaluated argument sub-expressions. Evaluate a sub-expression only when value is needed • to print • by primitive procedure (that is, primitive procedures are "strict" in their arguments)
Normal order evaluation does not go well with mutators. Consider: (set! a 4) (set! b (delay (+ 1 a))) (set! a 0) (force b) The value of a delayed operation depends on the actual time it is called, And this can be very confusing. Scheme does not use Normal order evaluation, except for streams, delay and force.
Forcing a delayed object many times Suppose we have the following scenario: (define x (delay (very-hard-function a))) (force x) (force x) We need to call the hard function twice. Scheme will automatically detect that this is the second time we try to evaluate the funtion and use the value we have evaluated before. Scheme makes it look like: (define x (delay (very-hard-function a))) (define b (force x)) b b
Beware: counter intuitive feature (define a 1) (define x (delay a)) (set! a 2) (force x) (set! a 3) (force x) The result is 2 (rather than 3)
How is it done? We redefine delay as follows (delay <exp>)translates to (memo-proc (lambda () <exp>)) (define (memo-proc proc) (let ((already-run? false) (result false)) (lambda () (if (not already-run?) (begin (set! result (proc)) (set! already-run? true) result) result))))
(define a 1)| GE Memo_proc: GE already-run: #f result: #f proc: p:proc b:(let .. (lambda () (if (not already-run?)… p: b:a p: b:(if (not already-run … (define x (delay a))| GE (define x (memo-proc (lambda () a)))| GE x: a:1
(set! a 3)| GE (set! a 2)| GE (force x)| GE Memo_proc: GE 3 2 proc: already-run: #f result: #f #t 2 p:proc b:(lambda () (if (not already-run?)… p: b:a p: b:(if (not already-run … (force x)| GE x: a:1