Streams, Delayed Evaluation and a Normal Order Interpreter

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.
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.
מבוא מורחב - שיעור 15 1 Lecture 15 Streams. מבוא מורחב - שיעור 15 2 Streams: Motivation (define (sum-primes a b) (define (iter count accum) (cond ((>
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.
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.
CS314 – Section 5 Recitation 9
(Thunking about Thunks)
Operational Semantics of Scheme
Lecture 4: Metacircles Eval Apply David Evans
CS 550 Programming Languages Jeremy Johnson
Basic Scheme February 8, 2007 Compound expressions Rules of evaluation
6.001 SICP Variations on a Scheme
6.001 SICP Compilation Context: special purpose vs. universal machines
The interpreter.
September 4, 1997 Programming Languages (CS 550) Lecture 6 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts.
Closures and Streams cs784(Prasad) L11Clos
Env. Model Implementation
Original material by Eric Grimson
Introduction to Functional Programming in Racket
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
FP Foundations, Scheme In Text: Chapter 14.
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
Lecture 13 - Assignment and the environments model Chapter 3
6.001 SICP Environment model
6.001 SICP Explicit-control evaluator
6.001 SICP Explicit-control evaluator
6.001 SICP Variations on a Scheme
Introduction to Functional Programming in Racket
Closures and Streams cs7100(Prasad) L11Clos
6.001 SICP Interpretation Parts of an interpreter
Assignments and Procs w/Params
Introduction to the Lab
topics interpreters meta-linguistic abstraction eval and apply
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
*Lecture based on notes from SICP
Lecture 25: The Metacircular Evaluator Eval Apply
Presentation transcript:

Streams, Delayed Evaluation and a Normal Order Interpreter September 4, 1997 Streams, Delayed Evaluation and a Normal Order Interpreter CS 550 Programming Languages Jeremy Johnson

September 4, 1997 Theme This lecture discusses the stream model of computation and an efficient method of implementation that relies on delayed evaluation. A variant of the scheme interpreter is presented that uses normal order evaluation. In order to overcome inefficiencies due to repeated evaluation, memorization is used. In this variant lists and streams are identical.

Outline Streams and delayed evaluation September 4, 1997 Outline Streams and delayed evaluation Lazy evaluation and normal order interpreter Memoization

Streams Sequence of elements (cons-stream x y) (stream-car s) September 4, 1997 Streams Sequence of elements (cons-stream x y) (stream-car s) (stream-cdr s) (stream-null? s) the-empty-stream

Streams Motivation and E.G. September 4, 1997 Streams Motivation and E.G. (define (sum-primes a b) (define (iter count accum) (cond ((> count b) accum) ((prime? count) (iter (+ count 1) (+ count accum))) (else (iter (+ count 1) accum)))) (iter a 0))

Streams Enumerate filter accumulate a,b Prime? +,0 September 4, 1997 Streams (define (sum-primes a b) (accumulate + (filter prime? (enumerate-interval a b)))) Enumerate filter accumulate a,b Prime? +,0

Streams are Not Lists Consider the following example September 4, 1997 Streams are Not Lists Consider the following example (car (cdr (filter prime? (enumerate-interval 10000 1000000)))) This would be extremely inefficient if implemented with lists Do not build the entire stream of elements Get the next element from the stream when needed Necessary for potentially infinite streams

September 4, 1997 Delayed Binding (cons-stream <a> <b>)  (cons <a> (delay <b>)) (define (stream-car stream) (car stream)) (define (stream-cdr stream) (force (cdr stream))) (delay <exp>)  (lambda () <exp>) (define (force delayed-object) (delayed-object))

Delayed Binding in Action September 4, 1997 Delayed Binding in Action (stream-car (stream-cdr (stream-filter prime? (stream-enumerate-interval 10000 1000000)))) (define (stream-enumerate-interval low high) (if (> low high) the-empty-stream (cons-stream low (stream-enumerate-interval (+ low 1) high)))) (cons 10000 (delay (stream-enumerate-interval 10001 1000000)))

Delayed Binding in Action September 4, 1997 Delayed Binding in Action (define (stream-filter pred stream) (cond ((stream-null? stream) the-empty-stream) ((pred (stream-car stream)) (cons-stream (stream-car stream) (stream-filter pred (stream-cdr stream)))) (else (stream-filter pred (stream-cdr stream))))) stream-cdr forces (cons 10001 (delay (stream-enumerate-interval 10002 1000000)))

Delayed Binding in Action September 4, 1997 Delayed Binding in Action (cons-stream (stream-car stream) (stream-filter pred (stream-cdr stream))) which in this case is (cons 10007 (delay (stream-filter prime? (cons 10008 (stream-enumerate-interval 10009 1000000))))))

September 4, 1997 Scheme Interpreter To evaluate a combination (a compound expression other than a special form), evaluate the subexpressions and then apply the value of the operator subexpression to the values of the operand subexpressions. To apply a compound procedure to a set of arguments, evaluate the body of the procedure in a new environment. To construct this environment, extend the environment part of the procedure object by a frame in which the formal parameters of the procedure are bound to the arguments to which the procedure is applied.

Scheme Interpreter: eval September 4, 1997 Scheme Interpreter: eval (define (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) (eval (cond->if exp) env)) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression type -- EVAL" exp))))

Scheme Interpreter: apply September 4, 1997 Scheme Interpreter: apply (define (apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type -- APPLY" procedure))))

September 4, 1997 Lazy Evaluation Language with normal order semantics. Compound procedures are non-strict, while primitive procedures remain strict. Procedure strict if args evaluated before entering Procedure non-strict if arg not evaluated before entering Delaying evaluation until last possible moment is called lazy evaluation. Delay evaluation of arguments by converting them to thunks. A thunk is forced only when its value is needed. Memoize thunks to avoid repeated evaluation.

Examples of Lazy Evaluation September 4, 1997 Examples of Lazy Evaluation (define (try a b) (if (= a 0) 1 b)) (try 0 (/ 1 0)) (define (unless condition usual-value exceptional-value) (if condition exceptional-value usual-value)) (unless (= b 0) (/ a b) (begin (display "exception: returning 0") 0))

Scheme Interpreter: eval September 4, 1997 Scheme Interpreter: eval (define (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) (eval (cond->if exp) env)) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression type -- EVAL" exp))))

Scheme Interpreter: apply September 4, 1997 Scheme Interpreter: apply (define (apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type -- APPLY" procedure))))

Lazy Scheme Interpreter: eval September 4, 1997 Lazy Scheme Interpreter: eval ((application? exp) (apply (actual-value (operator exp) env) (operands exp) env)) (define (eval-if exp env) (if (true? (actual-value (if-predicate exp) env)) (eval (if-consequent exp) env) (eval (if-alternative exp) env)))

Lazy Scheme Interpreter: apply September 4, 1997 Lazy Scheme Interpreter: apply (define (apply procedure arguments env) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure (list-of-arg-values arguments env))) ; changed ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) (list-of-delayed-args arguments env) ; changed (procedure-environment procedure)))) (else (error "Unknown procedure type -- APPLY" procedure))))

Lazy Scheme Interpreter: apply September 4, 1997 Lazy Scheme Interpreter: apply (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) (cons (delay-it (first-operand exps) env) (list-of-delayed-args (rest-operands exps)

Representing Thunks (define (actual-value exp env) September 4, 1997 Representing Thunks (define (actual-value exp env) (force-it (eval exp env))) (define (force-it obj) (if (thunk? obj) (actual-value (thunk-exp obj) (thunk-env obj)) obj)) (define (delay-it exp env) (list 'thunk exp env)) (define (thunk? obj)   (tagged-list? obj 'thunk))

Lazy Evaluation in Action September 4, 1997 Lazy Evaluation in Action (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))) (announce-output output-prompt) (user-print output))) (driver-loop)) (define the-global-environment (setup-environment)) (driver-loop) ;;; L-Eval input: (define (try a b) (if (= a 0) 1 b)) ;;; L-Eval value: ok (try 0 (/ 1 0)) 1

Memoization 5 4 3 3 2 2 1 2 1 1 1 1 (define (fib n) (cond ((= n 0) 0) September 4, 1997 Memoization (define (fib n) (cond ((= n 0) 0) ((= n 1) 1) (else (+ (fib (- n 1)) (fib (- n 2)))))) (fib 5) 5 4 3 3 2 2 1 2 1 1 1 1

Memoization (define (memoize f) (let ((table (make-hash))) (lambda (x) September 4, 1997 Memoization (define (memoize f) (let ((table (make-hash))) (lambda (x) (if (hash-has-key? table x) (hash-ref table x) (let ((result (f x))) (hash-set! table x result) result))))) (define memo-fib (memoize (lambda (n) (cond ((= n 0) 0) ((= n 1) 1) (else (+ (memo-fib (- n 1)) (memo-fib (- n 2))))))))

Memoized Thunks (define (evaluated-thunk? obj) September 4, 1997 Memoized Thunks (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) ; replace exp with its value (set-cdr! (cdr obj) '()) ; forget unneeded env result)) ((evaluated-thunk? obj) (thunk-value obj)) (else obj)))

September 4, 1997 Streams for Free Previous implementation of streams required new special forms delay and cons-stream and the reimplementation of list functions for streams. In the lazy evaluator lists and streams are identical! Just need to make sure that cons is non-strict Reimplement cons primitive Or implement cons, car, and cdr as functions (see lambda calculus)

September 4, 1997 Assignment Try out the streams example in Racket (streams are supported) the-empty-stream stream-enumerate-interval stream-filter prime? (stream-car (stream-cdr (stream-filter prime? (stream-enumerate-interval 10000 1000000))))

Assignment Modify the SICP interpreter to support streams September 4, 1997 Assignment Modify the SICP interpreter to support streams cons-stream delay force (use memorization to avoid repeated eval) stream-car stream-cdr Run the previous example using your modified interpreter

September 4, 1997 Assignment Run the previous example using the lazy evaluator. You will need to handle cons properly. Do this using the function implementation of cons, car and cdr. Implement the Y combinatory in the lazy evaluator