1 Lecture 20 Lazy Evaluation Continued (4.2.1, 4.2.2) MC-eval examples from exams (Time permitting)

Slides:



Advertisements
Similar presentations
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Advertisements

Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Scheme in Scheme?!? …the metacircular evaluator….
1 The metacircular evaluator Names Extend the calculator to store intermediate results as named values (define x (+ 4 5)) store result as x (+ x.
1 Programming Languages (CS 550) Operational Semantics of Scheme using Substitution and the Lambda Calculus Jeremy R. Johnson TexPoint fonts used in EMF.
Metacircular Evaluation SICP Chapter 4 Mark Boady.
1 Programming Languages (CS 550) Lecture 7 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts used in EMF. Read.
מבוא מורחב למדעי המחשב תרגול 13 Lazy Evaluation. Lazy Evaluation Implementation Two types of values – Delayed Values – Actual Values Introduce two functions.
1 The Metacircular Evaluator Chapter 4 Section 4.1 We will not cover every little detail in the lectures, so you MUST read Section 4.1 in full.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 11. Metacircular Evaluator 4.1, pages definitions file on web 2.
(define applicative-eval (lambda (exp) (cond ((atomic? exp) (eval-atomic exp)) ((special-form? exp) (eval-special-form exp)) ((list-form? exp) (eval-list.
1 Lecture 18 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure.
6.001 SICP 1 Normal (Lazy) Order Evaluation Memoization Streams.
Extended Introduction to CS Preparation for Final Exam.
David Evans CS200: Computer Science University of Virginia Computer Science Lecture 26: In Praise of Idleness.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
Extended Introduction to CS Preparation for Final Exam.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 21. Overview 1. Dynamic Binding 2. Lazy Evaluation 3. More MC-Eval 2.
Lexical vs. Dynamic Scope …where do I point to?. Intro… Remember in Scheme whenever we call a procedure we pop a frame and point it to where the procedure.
6.001 SICP SICP – Evaluation I Recitation 11/19/2004 Eval review Evaluation examples define lambda apply New language elements.
SICP Variations on a Scheme Scheme Evaluator – A Grand Tour Techniques for language design: Interpretation: eval/apply Semantics vs. syntax Syntactic.
SICP Infinite streams – using lazy evaluation Beyond Scheme – designing language variants: Streams – an alternative programming style!
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Scheme More MCE examples. Q1 new special form which defines global variables (static ) search the global environment – Variable exists: does nothing,
SICP Variations on a Scheme (2) Beyond Scheme – designing language variants: Lazy evaluation Complete conversion – normal order evaluator Upward.
The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using.
1 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure + symbol.
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is aa good way to learn more about programming languages  Interpreters are.
1 The metacircular evaluator (Cont.) Defining new procedures (define (lambda? e) (tag-check e 'lambda)) (define (eval exp env) (cond ((number? exp)
CS220 Programming Principles 프로그래밍의 이해 2002 가을학기 Class 15: Meta-Circular Evaluator 한 태숙.
SICP Interpretation Parts of an interpreter Arithmetic calculator Names Conditionals and if Storing procedures in the environment Environment as.
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
SICP Explicit-control evaluator Big ideas: how to connect evaluator to machine instructions how to achieve tail recursion Obfuscation: tightly.
The environment-based operational semantics Chapter
David Evans CS200: Computer Science University of Virginia Computer Science Lecture 29: Typed Scheme MC Escher, Liberation.
1 Read-Eval-Print Loop (define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (eval input the-global-env))) (announce-output.
1 Programming Languages (CS 550) Lecture 4 Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
1 Lecture 19 Dynamic Scoping Lazy Evaluation (4.2.1, 4.2.2)
1/ SICP Variations on a Scheme Scheme Evaluator – A Grand Tour Making the environment model concrete Defining eval defines the language –Provides.
CS 598 Scripting Languages Design and Implementation 10. Interpreters Part I: Lisp.
1 Lecture 19 Review last lecture on evaluator, Dynamic Scoping Lazy Evaluation (4.2.1, 4.2.2)
David Evans CS200: Computer Science University of Virginia Computer Science Lecture 27: Types of Types “It would appear.
1 The Evaluator. 2 Compiler vs. Interpreter Command Processing Unit The Computer Program in Low Level Machine Language Program in High Level Language.
6.037 Lecture 7B Scheme Variants Normal Order Lazy Evaluation Streams Edited by Mike Phillips & Ben Vandiver Original Material by Eric Grimson & Duane.
SICP Interpretation part 2 Store operators in the environment Environment as explicit parameter Defining new procedures.
(Thunking about Thunks)
Operational Semantics of Scheme
Lecture 4: Metacircles Eval Apply David Evans
6.001 SICP Variations on a Scheme
6.001 SICP Object Oriented Programming
September 4, 1997 Programming Languages (CS 550) Lecture 6 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts.
Env. Model Implementation
Original material by Eric Grimson
Streams Sections 3.5.1,3.5.2 Pages
The Metacircular Evaluator
Dynamic Scoping Lazy Evaluation
The Metacircular Evaluator
6.001 SICP Streams – the lazy way
The Metacircular Evaluator (Continued)
Lecture 27: In Praise of Idleness CS200: Computer Science
Lecture 26: The Metacircular Evaluator Eval Apply
6.001 SICP Further Variations on a Scheme
Streams, Delayed Evaluation and a Normal Order Interpreter
Lecture 12: Message passing The Environment Model
6.001 SICP Variations on a Scheme
6.001 SICP Interpretation Parts of an interpreter
topics interpreters meta-linguistic abstraction eval and apply
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
Lecture 25: The Metacircular Evaluator Eval Apply
Presentation transcript:

1 Lecture 20 Lazy Evaluation Continued (4.2.1, 4.2.2) MC-eval examples from exams (Time permitting)

2 lazy evaluation- reminder (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))))

3 Lazy Evaluation – l-eval Most of the work is in l-apply ; need to call it with: actual value for the operator just expressions for the operands the environment... (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))))

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

5 Representing Thunks Abstractly – a thunk is a "promise" to return a value when later needed ("forced") Concretely – our representation: thunk envexp

6 Thunks – delay-it and force-it (define (delay-it exp env) (list 'thunk exp env)) (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))) (define (actual-value exp env) (force-it (l-eval exp env)))

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

8 (l-eval ‘((lambda (x) (+ x x) ) (+ 1 1)) GE) (l-apply (actual-value ‘(lambda (x) (+ x x)) GE) ‘((+1 1 )) GE) (force-it (l-eval ‘(lambda (x) (+ x x)) GE)) ‘(procedure ‘(x) ‘((+ x x)) GE) (l-apply ‘(procedure ‘(x) ‘(+ x x) GE) ‘((+1 1 )) GE) (l-eval ‘(+ x x) E1) x : (‘thunk ‘(+1 1) GE) GE E1 (l-apply (actual-value ‘+ E1) ‘(x x) E1) (l-apply ‘(primitive #[add]) ‘(x x) E1) (apply-primitive-procedure ‘(primitive #[add]) (actual-value x E1)(actual-value x E1) ) (force-it (l-eval x E1)) (force-it (‘thunk ‘(+ 1 1) GE)) (actual-value ‘(+ 1 1) GE) (force-it (l-eval ‘(+ 1 1) GE)) ==> 2

9 (l-eval ‘(define f (lambda (x y) x)) GE) (eval-definition ‘(define f (lambda (x y) x)) GE) (define-variable! ‘f (l-eval ‘(lambda (x y) x) GE) GE) f: ‘(procedure ‘(x y) ‘(x) GE) GE

10 (l-eval ‘(f 1 1) GE) (l-apply (actual-value ‘f GE) ‘(1 1) GE) (force-it (l-eval ‘f GE)) ==> ‘(procedure ‘(x y) ‘(x) GE) (l-apply ‘(procedure ‘(x y) ‘(x) GE) ‘(1 1) GE) (l-eval ‘x E1) x : (‘thunk 1 GE) y: (‘thunk 1 GE) GE E1 ==> (‘thunk 1 GE)

11 (l-eval ‘(f (f 1 1) 1) GE) (l-apply (actual-value ‘f GE) ‘((f 1 1) 1) GE) (force-it (l-eval ‘f GE)) ‘(procedure ‘(x y) ‘(x) GE) (l-apply ‘(procedure ‘(x y) ‘(x) GE) ‘((f 1 1) 1) GE) (l-eval ‘x E1) x : (‘thunk ‘(f 1 1) GE) y: (‘thunk 1 GE) GE E1 ==> (‘thunk ‘(f 1 1) GE) Lets force this thunk..

12 (force-it (‘thunk ‘(f 1 1) GE)) (actual-value ‘(f 1 1) GE) (force-it (l-eval ‘(f 1 1) GE)) (force-it (l-apply (actual-value ‘f GE) ‘(1 1) GE)) (force-it (‘thunk 1 GE)) (actual-value 1 GE) (force-it (l-eval 1 GE)) ==> 1

13 Memo-izing Thunks Idea: once thunk exp has been evaluated, remember it If value is needed again, just return it rather than recompute thunk envexp Concretely – mutate a thunk into an evaluated-thunk evaluated- thunk result

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

15 Laziness and Language Design We have a dilemma with lazy evaluation Advantage: only do work when value actually needed Disadvantages –not sure when expression will be evaluated; can be very big issue in a language with side effects –may evaluate same expression more than once Alternative approach: give programmer control! Memoization doesn't fully resolve our dilemma Advantage: Evaluate expression at most once Disadvantage: What if we want evaluation on each use?

16 Variable Declarations: lazy and lazy-memo We want to extend the language as follows: (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 Controllably Memo-izing Thunks thunk – never gets memoized thunk-memo – first eval is remembered evaluated-thunk – memoized-thunk that has already been evaluated when forced Thunk Memo envexp evaluated- thunk result

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-args params arguments 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-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))))

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 Summary Lazy evaluation – control over evaluation models Convert entire language to normal order Upward compatible extension –lazy & lazy-memo parameter declarations

MC-eval Add a new special form – decrease (decrease proc num) If proc is compound, change its body so that it will return a number smaller by num than what it should have If proc is not compound return error Otherwise assume it returns a number

;;; M-Eval input: (define (double x) (+ x x)) ;;; M-Eval value: ok ;;; M-Eval input: (double 3) ;;; M-Eval value: 6 ;;; M-Eval input: (decrease double 1) ;;; M-Eval value: ok ;;; M-Eval input: (double 3) ;;; M-Eval value: 5 ;;; M-Eval input (decrease + 1) Error: can apply decrase only to compound procedures

Section A (define (decrease? exp) ___________________________ ) (define (decrease-proc-name exp) ______________________ ) (define (decrease-number exp) _______________________ )

(define (decrease? exp) ___(tagged-list? exp 'decrease)___________________ ) (define (decrease-proc-name exp) ____(cadr exp)__________________________ ) (define (decrease-number exp) _____(caddr exp)_______________________ )

Section B Decrease returns the new procedure body (define (modify-body proc expressions-list) (set-car! (cddr proc) expressions-list)) (define (eval-decrease exp env) (let* ((proc-name ________________________________ ) (number ________________________________ ) (proc (_________________________ proc-name env))) (cond ( ____________________________________ (error “Can apply decrease only to compound procedures”)) (else (modify-body proc (decrease proc number)) ‘ok))))

(define (modify-body proc expressions-list) (set-car! (cddr proc) expressions-list)) (define (eval-decrease exp env) (let* ((proc-name ____(decrease-proc-name exp)________ ) (number ____(decrease-number exp)_____________ ) (proc (_____mc-eval _____________ proc-name env))) (cond ( _____(not (compound-procedure? proc))____________ (error “Can apply decrease only to compound procedures”)) (else (modify-body proc (decrease proc number)) ‘ok))))