Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator

Slides:



Advertisements
Similar presentations
1 Programming Languages (CS 550) Mini Language Interpreter Jeremy R. Johnson.
Advertisements

Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
1 The metacircular evaluator Names Extend the calculator to store intermediate results as named values (define x (+ 4 5)) store result as x (+ x.
Metacircular Evaluation SICP Chapter 4 Mark Boady.
מבוא מורחב למדעי המחשב תרגול 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.
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.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
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.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
SICP Variations on a Scheme (2) Beyond Scheme – designing language variants: Lazy evaluation Complete conversion – normal order evaluator Upward.
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.
1 The Evaluator. 2 Compiler vs. Interpreter Command Processing Unit The Computer Program in Low Level Machine Language Program in High Level Language.
1 Lecture 20 Lazy Evaluation Continued (4.2.1, 4.2.2) MC-eval examples from exams (Time permitting)
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 Programming Languages (CS 550) Lecture 2 Summary Mini Language Interpreter Jeremy R. Johnson.
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
Functional Programming
Lecture 4: Metacircles Eval Apply David Evans
6.001 SICP Variations on a Scheme
6.001 SICP Object Oriented Programming
6.001 SICP Compilation Context: special purpose vs. universal machines
The interpreter.
Introduction to Scheme
Interpreters Study Semantics of Programming Languages through interpreters (Executable Specifications) cs7100(Prasad) L8Interp.
September 4, 1997 Programming Languages (CS 550) Lecture 6 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts.
Lecture 14 - Environment Model (cont.) - Mutation - Stacks and Queues
Closures and Streams cs784(Prasad) L11Clos
Env. Model Implementation
Original material by Eric Grimson
Nondeterministic Evaluation
Mini Language Interpreter Programming Languages (CS 550)
Streams Sections 3.5.1,3.5.2 Pages
The Metacircular Evaluator
Lecture 23 Pages : Separating Syntactic Analysis from Execution. We omit many details so you have to read the section in the book. The halting.
Lecture 18 Infinite Streams and
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 #9 מבוא מורחב.
Lecture 12: Message passing The Environment Model
Lecture 13 - Assignment and the environments model Chapter 3
Lecture 14 - Environment Model (cont.) - Mutation - Stacks and Queues
6.001 SICP Explicit-control evaluator
6.001 SICP Explicit-control evaluator
6.001 SICP Variations on a Scheme
6.001 SICP Interpretation Parts of an interpreter
Assignments and Procs w/Params
topics interpreters meta-linguistic abstraction eval and apply
*Lecture based on notes from SICP
Lecture 25: The Metacircular Evaluator Eval Apply
Presentation transcript:

Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator Lecture 22 Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator

We’ll write a lazy interpreter. Our machine language is regular Scheme. I.e., it runs in applicative order, and it’s not lazy except for special cases. We will write a lazy interpreter, that translates the input code to instructions for the Non-lazy machine.

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

Thunks- implementation env exp (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))

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

L-apply Notice that l-apply sends all arguments of (define (l-apply procedure arguments env) (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)))) Notice that l-apply sends all arguments of Compound procedures to sleep.

L-Eval Undelying procedures (like eval-definition) (define (l-eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env)) ((quoted? exp) (text-of-quotation exp)) ((assignment? exp) (eval-assignment exp env)) ((definition? exp) (eval-definition exp env)) ((if? exp) (eval-if exp env)) ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) ((begin? exp) (eval-sequence (begin-actions exp) env)) ((cond? exp) (l-eval (cond->if exp) env)) ((application? exp) (l-apply (actual-value (operator exp) env) (operands exp) (else (error "Unknown expression type – l-EVAL" exp)))) Undelying procedures (like eval-definition) call l-eval instead of eval. This is a top down, modular piece of software, built correctly with many layers of abstraction. However, since you havn’t built an interpreter before, we will not start directly a top down review of the process but rather first give a simplified example. Note that the use of a high level description in the main eval loop allows easy modification For possible changes to the language, but also makes it harder to add new constructs since they must Be added by changing this main eveal loop. L-eval does not wake up the arguments.

List-of-arg-values, list-of-delayed-args (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)))) (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))))

Let’s take an example (define d1 (delay-it exp env)) thunk env exp d1 is a pointer to a list. Exp is an abstract expression, and it is not evaluated.

What does l-eval do with a thunk? env exp answer It returns the address of d1, I.e., a pointer to the list. Exp is an abstract expression, and it is not evaluated.

What does force-it do with a thunk? env exp (force-it d1) (actual-value exp env) It evalutes exp in the environment env.

Taking a bigger example: infinite streams We want to work with non-strict cons, car, cdr. We work with our lazy evaluator Running over the non-lazy Scheme. We define: (define (cons x y) (lambda (m) (m x y))) (define (car z) (z (lambda (p q) p))) (define (cdr z) (z (lambda (p q) q)))

Our example; the ones stream. (define ones (cons 1 ones)) (car ones) We will do it in detail. We will be so tired after that, that we won’t need more examples… And we will also be running out of time…

So we start… The outer loop gets the input: exp= “(define ones (cons 1 ones))” It calls: (actual-value ‘(define ones (cons 1 ones)) GE) The actual-value from the outer loop, is the one sending the force, which wakes up all the sleeping values that are needed. It calls: (force-it (l-eval ‘(define ones (cons 1 ones)) GE))

It’s a definition, so… (force-it (eval-definition ‘(define ones (cons 1 ones)) GE)) (force-it (define-variable! (definition-variable ‘(define..)) (l-eval (definition-value ‘(define ..)) GE) GE)) (force-it (define-variable! ‘ones (l-eval ‘(cons 1 ones) GE) GE))

Eval again, and it’s … a procedure (force-it (define-variable! ‘ones (l-apply (actual-value ‘cons GE) ‘(1 ones) GE)) (actual-value ‘cons GE) (force-it (l-eval ‘cons GE)) (force-it #proc-..) #proc-.. (force-it (define-variable! ‘ones (l-apply #proc-cons ‘(1 ones) GE)) GE))

L-apply gets into action… (force-it (define-variable! ‘ones (l-eval-sequence ((lambda (m) (m x y))) (extend-environment ‘(x y) (list-of-delayed-args ‘(1 ones) GE) GE))

The whole point: the arguments are delayed. (force-it (define-variable! ‘ones (l-eval-sequence ((lambda (m) (m x y))) (extend-environment ‘(x y) (list (delay-it ‘1 GE) (delay-it ‘ones GE)) GE))

I.e., the arguments are thunks. (force-it (define-variable! ‘ones (l-eval (lambda (m) (m x y)) (extend-environment ‘(x y) (list (list 'thunk ‘1 GE) (list ‘thunk ‘ones GE)) GE))

L-eval again. This time.. A procedure (force-it (define-variable! ‘ones (make-procedure (lambda-parameters ‘(lambda (m) (m x y))) (lambda-body ‘(lambda (m) m x y))) (extend-environment ‘(x y) (list (list 'thunk ‘1 GE) (list ‘thunk ‘ones GE)) GE))

So.. We create the new environment We make the procedure We assign the procedure value to the variable ‘ones in GE define-variable! Returns ‘ok It’s not a thunk so force-it returns it as well. GE E1 x: (list 'thunk ‘1 GE) y: (list ‘thunk ‘ones GE)) ones: p: m body: (m x y)

Now we try ‘(car ones) (actual-value ‘(car ones) GE) (force-it (l-eval ‘(car ones) GE)) (force-it (l-apply #proc-car ‘ones GE)) (force-it (l-eval-sequence ‘((z (lambda (p q) p))) (extend-environment ‘(z) (list-of-delayed-args ‘ones GE) GE)))

L-eval gets ready.. (force-it (l-eval ‘(z (lambda (p q) p)) (extend-environment ‘(z) (list (list 'thunk ‘ones GE)) GE))) l-eval looks at the expression, and it’s a compound procedure.

L-eval moves (force-it (l-eval (l-apply (actual-value ‘z (extend-env ..)) ‘(lambda (p q) p) (extend-environment ‘(z) (list (list 'thunk ‘ones GE)) GE)))

(actual-value ‘z (extend-env ..)) Actual-value opens to: (force-it (l-eval ‘z (extend-environment ‘(z) (list (list 'thunk ‘ones GE)) GE))) (force-it (list ‘thunk ‘ones GE)) (actual-value ‘ones GE) It is NOT a thunk, so we get: ones the address of The procedure ones.

Back to L-eval (force-it (l-eval (l-apply ones ‘(lambda (p q) p) (extend-environment …))) We move the ball to l-apply…

L-eval again.. (force-it (l-eval (l-eval ‘(m x y) (extend-environment (list-of-delayed-args ‘(lambda (p q) p) (extend-env…)) ‘(x y) (list (list 'thunk ‘1 GE) (list ‘thunk ‘ones GE)) GE)))))) E2

And l-eval again… L-eval gets into action. It calls: (l-apply (actual-value (operator exp) E2) … This forces m, and assigns m the procedure (lambda (p q) p) At this stage x,y are still delayed. We now get: (l-apply (lambda (p q) p) ‘(x y) E2)

And l-apply again… (l-eval ‘p (extend-environment ‘(p q) (list-of-delayed-args ‘(x y) E2) E2)) In the extended environment E2, p gets bounded to (list ‘thunk x E1) And so this is what l-eval returns. (list ‘thunk x E1)

We know force it. Obj = (list ‘thunk x E1) (actual-value (thunk-exp obj) (thunk-env obj))) (actual-value x E1) (force-it (l-eval x E1)) (force-it (list ‘thunk ‘1 GE)) ‘1 We had to force the object twice!

Add-lists and the integers Now consider: (define (add-lists list1 list2) (cond ((null? List1) list2) ((null? List2) list1) (else (cons (+ (car list1) (car list2)) (add-lists (cdr list1) (cdr list2)))))) (define ones (cons 1 ones)) (define integers (cons 1 (add-lists one integers))

Upper vs. lower language Try to figure out what happens in the lower level with the Integers example. It is very difficult for humans to think in machine-language It is impossible for machines to think in upper language The interpreter (compiler) bridges the gap.

And another moral: it pays off to program well The actual process that takes place when evaluating integers, Is techniquly complicated. A process can be techniqly complicated but still (very) efficient. With careful planning, complicated processes can have a Short, Concise Efficient implementation as a sequence of simple well-defined procedures.