מבוא מורחב למדעי המחשב תרגול 13

29
בבבב בבבבב בבבבב בבבבב בבבבב13 Lazy Evaluation

description

מבוא מורחב למדעי המחשב תרגול 13. Lazy Evaluation. Lazy Evaluation Implementation. Two types of values Delayed Values Actual Values Introduce two functions (actual-value exp env ) returns real value (delay-it exp env ) returns a “ thunk ”. Lazy Evaluation. - PowerPoint PPT Presentation

Transcript of מבוא מורחב למדעי המחשב תרגול 13

Page 1: מבוא מורחב למדעי המחשב תרגול 13

המחשב למדעי מורחב מבוא13תרגול

Lazy Evaluation

Page 2: מבוא מורחב למדעי המחשב תרגול 13

Lazy Evaluation Implementation

• Two types of values– Delayed Values – Actual Values

• Introduce two functions– (actual-value exp env) returns real value– (delay-it exp env) returns a “thunk”

Page 3: מבוא מורחב למדעי המחשב תרגול 13

3

Lazy Evaluation• Normal order - delay operands (only)• Special forms and compound procedures may return

delayed objects • (l-eval exp env) may return delayed value• We use actual-value only if we have to,

otherwise we use l-eval• Primitives must receive the actual value• Print-on-screen is actual value

Page 4: מבוא מורחב למדעי המחשב תרגול 13

4

Lazy Evaluation – l-eval(define (l-eval exp env) (cond ((self-evaluating? exp) exp) ... ((application? exp (l-apply (actual-value (operator exp) env)

(operands exp) env))

(else (error "Unknown expression" exp))))

Compare with mc-eval:((application? exp) (mc-apply (mc-eval (operator exp) env) (list-of-values (operands exp) env)))

Page 5: מבוא מורחב למדעי המחשב תרגול 13

Lazy Evaluation – l-apply(define (l-apply procedure arguments env) ; changed (cond ((primitive-procedure? procedure) (apply-primitive-procedure

procedure (list-of-arg-values arguments env)))

((compound-procedure? procedure) (l-eval-sequence (procedure-body procedure)

(extend-environment (procedure-parameters procedure) (list-of-delayed-args arguments env)

(procedure-environment procedure)))) (else (error "Unknown proc" procedure))))

Page 6: מבוא מורחב למדעי המחשב תרגול 13

Actual vs. Delayed Values(define (actual-value exp env) (force-it (l-eval exp env)))

(define (list-of-delayed-args exps env) (if (no-operands? exps) '() (cons (delay-it (first-operand exps) env) (list-of-delayed-args (rest-operands exps) env))))

(define (list-of-arg-values exps env) (if (no-operands? exps) '() (cons (actual-value (first-operand exps) env) (list-of-arg-values (rest-operands exps) env))))

Page 7: מבוא מורחב למדעי המחשב תרגול 13

7

Representing Thunks

• In our implementation we represent “Thunks” using a tagged list:

thunk envexp

Page 8: מבוא מורחב למדעי המחשב תרגול 13

Thunks – abstractionConstructor:(define (delay-it exp env) (list 'thunk exp env))

Selectors:(define (thunk? obj) (tagged-list? obj 'thunk))(define (thunk-exp thunk) (cadr thunk))(define (thunk-env thunk) (caddr thunk))

(define (force-it obj) (cond ((thunk? obj) (actual-value (thunk-exp obj) (thunk-env obj))) (else obj)))

Page 9: מבוא מורחב למדעי המחשב תרגול 13

Lazy Evaluation – other changes needed

• Example – need actual predicate value in conditional if...(define (l-eval-if exp env) (if (true? (actual-value (if-predicate exp) env)) (l-eval (if-consequent exp) env) (l-eval (if-alternative exp) env)))

• Example – don't need actual value in assignment...

(define (l-eval-assignment exp env) (set-variable-value! (assignment-variable exp) (l-eval (assignment-value exp) env) env) 'ok)

Might return delayed values

No change relative to mc-eval version!

Page 10: מבוא מורחב למדעי המחשב תרגול 13

Lazy Evaluation – more changes(define input-prompt ";;; L-Eval input:")(define output-prompt ";;; L-Eval value:")

(define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (actual-value input the-global-environment))) (cond ((eq? output exit-object) 'done) (else (announce-output output-prompt) (user-print output) (driver-loop))))))

Page 11: מבוא מורחב למדעי המחשב תרגול 13

Lazy Evaluation - Example

• What happens when this code is executed using mc-eval?

• Can we add “unless” to the metacircular evaluator?

(define (unless condition usual exceptional) (if condition exceptional usual))

(define (factorial n) (unless (= n 1) (* n (factorial (- n 1))) 1))

Page 12: מבוא מורחב למדעי המחשב תרגול 13

12

Memoizing Thunks• Only evaluate

Thunks once

• Mutate our data structure when the thunk is first evaluated

thunk envexp

evaluated-thunk

result

Page 13: מבוא מורחב למדעי המחשב תרגול 13

13

Thunks – Memoizing Implementation (define (evaluated-thunk? obj) (tagged-list? obj 'evaluated-thunk))(define (thunk-value evaluated-thunk) (cadr evaluated-thunk))

(define (force-it obj) (cond ((thunk? obj) (let ((result (actual-value (thunk-exp obj) (thunk-env obj)))) (set-car! obj 'evaluated-thunk) (set-car! (cdr obj) result) (set-cdr! (cdr obj) '()) result)) ((evaluated-thunk? obj) (thunk-value obj)) (else obj)))

Page 14: מבוא מורחב למדעי המחשב תרגול 13

Timing Comparison

• How would the different implementations (mc-eval, lazy, lazy + memoization) compute the following:

(define (square x) (* x x))(square (fib 100))

Page 15: מבוא מורחב למדעי המחשב תרגול 13

Example

• What is the result of (func 1)?• Is it similar to evaluation with mc-eval?

(define (func x) (define (p e) e x) (p (set! x (cons x '(2)))))

Page 16: מבוא מורחב למדעי המחשב תרגול 13

lazy and lazy-memo

• We want to extend the original mc-eval:

(lambda (a (b lazy) c (d lazy-memo)) ...)

– "a", "c" are strict variables (evaluated before procedure application

– "b" is lazy; it gets (re)-evaluated each time its value is actually needed

– "d" is lazy-memo; it gets evaluated the first time its value is needed, and then that value is returned again any other time it is needed again.

Page 17: מבוא מורחב למדעי המחשב תרגול 13

Controllably Memo-izing Thunks• thunk – never gets memoized• thunk-memo – first eval is remembered• evaluated-thunk – memoized-thunk that has

already been evaluated

whenforced

ThunkMemo

envexp

evaluated-thunk

result

Page 18: מבוא מורחב למדעי המחשב תרגול 13

A new version of delay-it

• Look at the variable declaration to do the right thing...

(define (delay-it decl exp env) (cond ((not (declaration? decl)) (l-eval exp env)) ((lazy? decl)

(list 'thunk exp env)) ((memo? decl)

(list 'thunk-memo exp env)) (else (error "unknown declaration:" decl))))

Page 19: מבוא מורחב למדעי המחשב תרגול 13

Changes to force-it(define (force-it obj) (cond ((thunk? obj) ;eval, but don't remember it (actual-value (thunk-exp obj) (thunk-env obj))) ((memoized-thunk? obj) ;eval and remember (let ((result (actual-value (thunk-exp obj) (thunk-env obj)))) (set-car! obj 'evaluated-thunk) (set-car! (cdr obj) result) (set-cdr! (cdr obj) '()) result)) ((evaluated-thunk? obj) (thunk-value obj)) (else obj)))

Page 20: מבוא מורחב למדעי המחשב תרגול 13

Changes to l-apply• Key: in l-apply, only delay "lazy" or "lazy-memo" params

– make thunks for "lazy" parameters– make memoized-thunks for "lazy-memo" parameters

(define (l-apply procedure arguments env) (cond ((primitive-procedure? procedure) ...) ; as before; apply on list-of-arg-values ((compound-procedure? procedure) (l-eval-sequence (procedure-body procedure)

(let ((params (procedure-parameters procedure))) (extend-environment

(map parameter-name params) (list-of-delayed-args params arguments env) (procedure-environment procedure)))))

(else (error "Unknown proc" procedure))))

Page 21: מבוא מורחב למדעי המחשב תרגול 13

Deciding when to evaluate an argument...

• Process each variable declaration together with application subexpressions – delay as necessary:

(define (list-of-delayed-args var-decls exps env) (if (no-operands? exps) '() (cons (delay-it (first-variable var-decls) (first-operand exps) env) (list-of-delayed-args (rest-variables var-decls)

(rest-operands exps) env))))

Page 22: מבוא מורחב למדעי המחשב תרגול 13

Syntax Extensions – Parameter Declarations

(define (first-variable var-decls) (car var-decls))(define (rest-variables var-decls) (cdr var-decls))(define declaration? pair?)

(define (parameter-name var-decl) (if (pair? var-decl) (car var-decl) var-decl))

(define (lazy? var-decl) (and (pair? var-decl) (eq? 'lazy (cadr var-decl))))

(define (memo? var-decl) (and (pair? var-decl) (eq? 'lazy-memo (cadr var-decl))))

Page 23: מבוא מורחב למדעי המחשב תרגול 13

Exam Question

• Assume we have the following special form:– (static <variable> <value>)

• Evaluation– If <variable> exists in the global environment,

do nothing– Otherwise evaluate <value> in the current

environment and bind <variable> to the result of the evaluation in the global environment

Page 24: מבוא מורחב למדעי המחשב תרגול 13

> (define (f) (static x 1) x)> (define (g x) (static x (* 2 2)) x)> (g 7)

> (f)

> (set! x (+ x 1))> (f)

7

4

5

Page 25: מבוא מורחב למדעי המחשב תרגול 13

How would the code evaluate?(define (id x) (static counter 0) (set! counter (+ counter 1)) x) (define (foobar counter) (id (begin (static counter 5) (id counter)))) (foobar 10) counter

Page 26: מבוא מורחב למדעי המחשב תרגול 13

GE id:

p:xb:…

foobar:

p:counterb:…

E1counter:10

E2x:10

counter:5/6

E3x:10

/7

mc-eval, static binding

counter7

(foobar 10)10

Page 27: מבוא מורחב למדעי המחשב תרגול 13

GE id:

p:xb:…

foobar:

p:counterb:…

E1counter:10

E2x:

/1

E3x:10

l-eval, static binding

thunk(begin…)

counter:0

In (driver-loop):(let ((output (actual-value input the-global-environment)))

/2

counter2

(foobar 10)10

Page 28: מבוא מורחב למדעי המחשב תרגול 13

GE id:

p:xb:…

foobar:

p:counterb:…

E1counter:10

E2x:10

counter:5

XX 11

E3x:10

XX 12

mc-eval, dynamic binding

counter5

(foobar 10)10

Page 29: מבוא מורחב למדעי המחשב תרגול 13

GE id:

p:xb:…

foobar:

p:counterb:…

E1counter:10

E2x:

counter:0

XX 11

E3x:11

XX 12

l-eval, dynamic binding

counter0

(foobar 10)11

thunk(begin…)

In (driver-loop):(let ((output (actual-value input the-global-environment)))