1 / 29

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

מבוא מורחב למדעי המחשב תרגול 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.

manchu
Download Presentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. מבוא מורחב למדעי המחשבתרגול 13 Lazy Evaluation

  2. 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”

  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

  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)))

  5. 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))))

  6. Actual vs. Delayed Values (define (actual-value exp env) (force-it (l-eval exp env))) (define (list-of-arg-values expsenv) (if (no-operands? exps) '() (cons (actual-value (first-operand exps) env) (list-of-arg-values (rest-operands exps) env)))) (define (list-of-delayed-argsexpsenv) (if (no-operands? exps) '() (cons (delay-it (first-operand exps) env) (list-of-delayed-args (rest-operands exps) env))))

  7. thunk exp env Representing Thunks • In our implementation we represent “Thunks” using a tagged list:

  8. Thunks – abstraction Constructor: (define (delay-it exp env) (list 'thunk exp env)) Selectors: (define (thunk? obj) (tagged-list? obj 'thunk)) (define (thunk-exp thunk) (cadrthunk)) (define (thunk-envthunk) (caddrthunk)) (define (force-it obj) (cond ((thunk? obj) (actual-value (thunk-exp obj) (thunk-envobj))) (else obj)))

  9. 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))) Might return delayed values • 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) No change relative to mc-eval version!

  10. 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))))))

  11. 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))

  12. thunk exp env evaluated-thunk result MemoizingThunks • Only evaluate Thunks once • Mutate our data structure when the thunk is first evaluated

  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-envobj)))) (set-car! obj 'evaluated-thunk) (set-car! (cdrobj) result) (set-cdr! (cdrobj) '()) result)) ((evaluated-thunk? obj) (thunk-value obj)) (else obj)))

  14. Timing Comparison • How would the different implementations (mc-eval, lazy, lazy + memoization) compute the following: (define (square x) (* x x)) (square (fib 100))

  15. 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)))))

  16. 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.

  17. when forced evaluated-thunk result Controllably Memo-izing Thunks • thunk – never gets memoized • thunk-memo – first eval is remembered • evaluated-thunk – memoized-thunk that has already been evaluated Thunk Memo exp env

  18. 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))))

  19. 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)))

  20. 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-argsparamsarguments env) (procedure-environment procedure))))) (else (error "Unknown proc" procedure))))

  21. Deciding when to evaluate an argument... • Process each variable declaration together with application subexpressions – delay as necessary: (define (list-of-delayed-argsvar-declsexpsenv) (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))))

  22. 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))))

  23. 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 environmentand bind <variable> to the result of the evaluation in the global environment

  24. > (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

  25. 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

  26. mc-eval, static binding GE id: foobar: counter:5 /6 /7 E3 E2 E1 counter:10 x:10 p:xb:… p:counterb:… x:10 (foobar 10) 10 counter 7

  27. l-eval, static binding GE id: foobar: counter:0 /1 /2 E3 E1 E2 counter:10 thunk x: p:xb:… p:counterb:… (begin…) x:10 (foobar 10) 10 counter 2 In (driver-loop): (let ((output (actual-value input the-global-environment)))

  28. mc-eval, dynamic binding GE id: foobar: counter:5 E1 E2 E3 XX 11 XX 12 counter:10 x:10 x:10 p:xb:… p:counterb:… (foobar 10) 10 counter 5

  29. l-eval, dynamic binding GE id: foobar: counter:0 E1 E2 E3 XX 11 XX 12 counter:10 thunk x: x:11 p:xb:… p:counterb:… (begin…) (foobar 10) 11 In (driver-loop): (let ((output (actual-value input the-global-environment))) counter 0

More Related