Imperative Programming: Mutable data (local state, letrec, set!) Example 1: counter (define counter (let ((count 0)) (lambda () (set! count (+ count 1))

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.
1-1 An Introduction to Scheme March Introduction A mid-1970s dialect of LISP, designed to be a cleaner, more modern, and simpler version than.
Metacircular Evaluation SICP Chapter 4 Mark Boady.
Evaluators for Functional Programming Chapter 4 1 Chapter 4 - Evaluators for Functional Programming.
Imperative Programming: Mutable data (local state, letrec, set!) Example 1: counter (define counter (let ((count 0)) (lambda () (set! count (+ count 1))
Imperative Programming. Back to scheme Scheme is a functional language In some cases there is a need to capture objects state E.g. bank account.
Imperative Programming Chapter 6 1. Local State Real world software like: Banks Course grading system Are state systems. i.e. they change along time:
(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.
1 Scheme Scheme is a functional language. Scheme is based on lambda calculus. lambda abstraction = function definition In Scheme, a function is defined.
6.001 SICP SICP – October environment Trevor Darrell 32-D512 Office Hour: W web page:
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
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.
SchemeCOP Introduction to Scheme. SchemeCOP Scheme Meta-language for coding interpreters –“ clean ” semantics Scheme = LISP + ALGOL –simple.
PPL Syntax & Formal Semantics Lecture Notes: Chapter 2.
PPL Syntax & Formal Semantics Lecture Notes: Chapter 2.
The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using.
1 Saves repeated renaming and substitution: explicit substitution is replaced by variable bindings using new data structures (frame, environment). Can.
1 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure + symbol.
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 Subt. model interpreter: Structure of the interpreter ASP Derived expressions Core Test Data structures Utils A racket lib Proc / Primitive-Proc. Global.
1 The Evaluator. 2 Compiler vs. Interpreter Command Processing Unit The Computer Program in Low Level Machine Language Program in High Level Language.
The environment-based operational semantics Chapter
MT311 Java Application Development and Programming Languages Li Tak Sing( 李德成 )
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
1 Subt. model interpreter: Introduction Abstract Syntax Parser Abstract Syntax Parser Derived Expressions Core Test Data Structures Utils (a racket lib)
Example 1: counter (set! vs set-box!) 1 Imperative Programming: Mutable data and local state (define counter (let ((count 0)) (lambda () (set! count (+
Example 1: counter (set! vs set-box!) 1 Imperative Programming: Mutable data and local state (define counter (let ((count 0)) (lambda () (set! count (+
Imperative Programming Chapter 6 1. Local State Real world software like: Banks Course grading system Are state systems. i.e. they change along time:
1 Programming Languages (CS 550) Lecture 4 Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
1 Env. Model Implementation & Analyzer Practice Session #10 Env. Model Implementation & Analyzer Practice Session #10.
CS61A Lecture Colleen Lewis. Clicker poll Do you feel comfortable posting questions to piazza? A)Yes with my classmates and instructors.
Evaluators for Functional Programming 1. How to describe (specify) a programming language? 1.Syntax: atoms, primitives, combination and abstraction means.
SICP Interpretation part 2 Store operators in the environment Environment as explicit parameter Defining new procedures.
Operational Semantics of Scheme
6.001 SICP Variations on a Scheme
6.001 SICP Object Oriented Programming
The interpreter.
Introduction to Scheme
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
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.
FP Foundations, Scheme In Text: Chapter 14.
Dynamic Scoping Lazy Evaluation
The Metacircular Evaluator
The Metacircular Evaluator (Continued)
6.001 SICP Further Variations on a Scheme
Streams, Delayed Evaluation and a Normal Order Interpreter
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 Variations on a Scheme
Lecture 14: The environment model (cont
6.001 SICP Interpretation Parts of an interpreter
Lecture 13: Assignment and the Environment Model (EM)
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:

Imperative Programming: Mutable data (local state, letrec, set!) Example 1: counter (define counter (let ((count 0)) (lambda () (set! count (+ count 1)) count))) (define counter (let ((count 0)) (lambda () (set! count (+ count 1)) count))) How would this work in the substitution model? app-eval [ ((lambda (count) (lambda () (begin (set! count (+ count 1)) count)) 0 )] app-eval [ (lambda () (begin (set! 0 (+ 0 1)) 0)) ] app-eval [ (begin (set! 0 (+ 0 1)) 0) ] ==> 0 The substitution model cannot account for change! change requires objects that keep local states. The substitution step has to be strengthened to enable binding of variables (parameters) to actual argument values. 1

GE counter (lambda () (set!... E1 count=0 P = B= (set!... count P = count B= (lambda () (set!... count (set!... count E2 1 > (counter) 2 Note that count is the local state of the counter object. Conclusion: In functional languages, objects are implemented as runtime generated closures. > (counter) ;;; How would the box diagram look like? 1 Example 1: counter (define counter (let ((count 0)) (lambda () (set! count (+ count 1)) count))) (define counter (let ((count 0)) (lambda () (set! count (+ count 1)) count))) 2 Imperative Programming: Mutable data (local state, letrec, set!)

Example 2: letrec The letrec expression can be used to define local recursive procedures. The evaluation rule for this expression is not supported by the functional programming model (e.g, applicative-eval) without rewriting the code of the recursive procedure. However, it can be supported by the imperative programming with the environment model. (letrec ((f1 lambda-exp1)... (fn lambda-expn)) e1...em) (let ((f1 ’unassigned)... (fn ’unassigned)) (set! f1 lambda-exp1)... (set! fn lambda-expn) e1...em) To support the evaluation of a letrec expression, it is handled as a derived expression: 3 Imperative Programming: Mutable data (local state, letrec, set!)

Example 2: letrec env-eval[ ( letrec ( (fact ( lambda (n) (if (= n 0) 1 (* n (fact (- n 1)))) )) (fact 3) ),GE]==> Assume letrec was translated to let which was translated to an application… env-eval[ (( lambda (fact) (set! fact (lambda (n) (if (= n 0) 1 (* n (fact (- n 1))))) (fact 3) ) 'uassigned ), GE] ==> env-eval[ (set! fact (lambda (n) (if (= n 0) 1 (* n (fact (- n 1))))), E1] GE Params: fact Body: (set!... (fact 3) (A) fact='unassigned E1 (set!.. (fact 3) Remains to evaluate… (next slide) Params: n Body: (if… ) (B) 4 Imperative Programming: Mutable data (local state, letrec, set!)

Example 2: letrec ==> env-eval[ (fact 3), E1 ] env-eval[ fact, E1 ] ==> lookup-varibale-value (fact,E1) = (B) env-eval[ 3, E1 ] ==> 3 Let E2 be the extended environment… env-eval[(* n (fact (- n 1))), E2] ==> env-eval[*,E2] ==> ==> env-eval [n,E2]==> 3 (lookup) ==> env-eval[(fact (- n 1)), E2] ==> env-eval[fact, E2] ==> lookup-variable-value(fact,E2): (B) … n = 3 E2 …(* n (fact (- n 1)))… 5 GE Params: fact Body: (set!... (fact 3) (A) fact='unassigned E1 (set!.. (fact 3) Params: n Body: (if… ) (B) Imperative Programming: Mutable data (local state, letrec, set!)

Example 2: letrec Compare the last diagram with the diagram resulting from using let instead of letrec: Env-eval[ (letrec ((fact (lambda (n) (if (= n 0) 1 (* n (fact (- n 1)))))) (fact 3)),GE]==> fact E1 GE Params: fact Body: (set.. (fact 3) (A) (set.. (fact 3) Params: n Body: (if… ) (B) (a)The set statement is removed for A’s body (according to the way a let expression is derived) (b)Procedure B “points” to the GE! B is not defined within a closure (as earlier), but as an argument evaluated in the GE. (c)When evaluating B’s body, fact is unbound! 6 Env-eval[ ( (lambda (fact) (fact 3)) (lambda (n) (if (= n 0) 1 (* n (fact (- n 1))))) ), GE] Imperative Programming: Mutable data (local state, letrec, set!)

Example 3: A chess player object: (define make-player (lambda (total) (letrec ((steps 0) (get-steps (lambda () steps)) (set-steps (lambda () (set! steps (+ steps 1)))) (get-total (lambda () total)) (set-total (lambda (piece) (let ((piece-value (cond ( (eq? piece 'queen) 9) ( (eq? piece 'rook) 5) ( (eq? piece 'bishop) 3) ( (eq? piece 'knight) 3) ( (eq? piece 'pawn) 1) ( else 0)))) (set! total (- total piece-value))))) (dispatch (lambda (m) (cond ((eq? m 'set-total) set-total) ((eq? m 'set-steps) set-steps) ((eq? m 'get-total) get-total) ((eq? m 'get-steps) get-steps) (else (error "Unknown request"))))) ) dispatch))) (define make-player (lambda (total) (letrec ((steps 0) (get-steps (lambda () steps)) (set-steps (lambda () (set! steps (+ steps 1)))) (get-total (lambda () total)) (set-total (lambda (piece) (let ((piece-value (cond ( (eq? piece 'queen) 9) ( (eq? piece 'rook) 5) ( (eq? piece 'bishop) 3) ( (eq? piece 'knight) 3) ( (eq? piece 'pawn) 1) ( else 0)))) (set! total (- total piece-value))))) (dispatch (lambda (m) (cond ((eq? m 'set-total) set-total) ((eq? m 'set-steps) set-steps) ((eq? m 'get-total) get-total) ((eq? m 'get-steps) get-steps) (else (error "Unknown request"))))) ) dispatch))) We’ll examine a simpler representation of a chess player by using only the procedure set-total. A chess player object is represent by a dispatch procedure. Based on a given message it invokes internal procedures of the object. total and steps which keep track of the player’s points and the number of steps respectively, are the object’s local state variables. 7 Imperative Programming: Mutable data (local state, letrec, set!)

(define make-player (lambda (total) (letrec ((steps 0) (get-steps (lambda () steps)) … (set-total (lambda (piece) (let ((piece-value (cond ( (eq? piece 'queen) 9) … ( else 0)))) (set! total (- total piece-value))))) (dispatch (lambda (m) (cond ((eq? m 'set-total) set-total) … (else (error "Unknown request"))))) ) dispatch))) (define make-player (lambda (total) (letrec ((steps 0) (get-steps (lambda () steps)) … (set-total (lambda (piece) (let ((piece-value (cond ( (eq? piece 'queen) 9) … ( else 0)))) (set! total (- total piece-value))))) (dispatch (lambda (m) (cond ((eq? m 'set-total) set-total) … (else (error "Unknown request"))))) ) dispatch))) 8 Imperative Programming: Mutable data (local state, letrec, set!) (define player1 (make-player 39)) P=(total) B=(letrec… make-player player1 GE E2 steps = ‘unassigned get-steps = ‘unassigned … set-total = ‘unassigned dispatch = ‘unassigned E1 total = 39 (letrec… P=get-steps… B= (set! get-steps (lambda() steps)) … dispatch 0 P= B= steps P=piece B=(let…) P=m B=(cond…) ((player1 ‘set-total) ‘queen) E3 m = ‘set-total (cond… E4 piece = ‘queen (let… 30

Example 2: A chess player object: (define make-player (lambda (total) (lambda (piece) (let ((piece-value (cond ((eq? piece 'queen) 9) ((eq? piece 'rook) 5) ((eq? piece 'bishop) 3) ((eq? piece 'knight) 3) ((eq? piece 'pawn) 1) (else 0)))) (set! total (- total piece-value)) total)))) (define make-player (lambda (total) (lambda (piece) (let ((piece-value (cond ((eq? piece 'queen) 9) ((eq? piece 'rook) 5) ((eq? piece 'bishop) 3) ((eq? piece 'knight) 3) ((eq? piece 'pawn) 1) (else 0)))) (set! total (- total piece-value)) total)))) We represent a chess player by a procedure that keeps track of his total points: Initially, a player has a certain total number of points and he loses points according to pieces he loses in the game. Local state (initialized) ((make-player 39) ‘queen) E1 total = 39 (lambda (piece)… P=(piece) B=(let ((piece-value… E2 Piece = ‘queen (let ((piece-value… P=(piece-value) B=(set!... total… P=(total) B=(lambda (piece)… make-player GE E3 piece-value = 9 (set! total (- total piece-value)) total… 30 9 Imperative Programming: Mutable data (local state, letrec, set!)

10 Question1: Can a while expression be supported in a functional programming evaluator? NO! in functional programming there is no change of state. Particularly, the result of evaluating the clause of a while loop will always remain the same. An ability to change state is required! In the (Meta-Circular Environment Based) interpreter for imperative programming, support for set! expressions is added. This gives motivation for supporting while expressions: > (define x 0) > (define n 4) > (while (> n 0) (begin (set! x (+ x n)) (set! n (- n 1))) ) > x 10 Imperative Programming Evaluator: Adding while expressions We would like to support a while expression with the following Syntax: (while ). Fore example:

11 Question2: Can while be defined as a user procedure (in the imperative model)? (define while (lambda (pred body) (if pred (begin (body) (while pred body)))) > (define x 2) > (while (> x 0) (lambda () (begin (set! x (+ x n)) (display x))) ) So the answer is?...Yes! BUT, only in the normal evaluation approach. (define while (lambda (pred body) (if pred (begin (body) (while pred body)))) According to the normal evaluation approach, the predicate must be evaluated. The expression constituting pred is passed to recursive calls, as opposed to the value of the pred expression in the eager approach > (while (> x 0) (lambda () (begin (set! x (+ x n)) (display x)))) 1 Endless loop… After the first time pred is evaluated to #t, It remains #t in every recursive call. Imperative Programming Evaluator: Adding while expressions

(define while? (lambda (exp) (tagged-list? exp 'while))) To support while expressions, we add the appropriate parser procedures: (define while-pred (lambda (exp) (car (get-content exp)))) (define while-pred (lambda (exp) (car (get-content exp)))) (define while-body (lambda (exp) (cadr (get-content exp)))) (define while-body (lambda (exp) (cadr (get-content exp)))) 12 Imperative Programming Evaluator: Adding while expressions > (env-eval '(define x 0) the-global-env) > (env-eval '(define n 4) the-global-env) > (env-eval '(while (> n 0) (begin (set! x (+ x n)) (set! n (- n 1))) ) the-global-env) ok > (env-eval x the-global-env) 10

(define derived? (lambda (exp) (or … (while? exp)))) (define shallow-derive (lambda (exp) (cond … ((while? exp) (while->iteration-expression exp))))) (define shallow-derive (lambda (exp) (cond … ((while? exp) (while->iteration-expression exp))))) 1. Add to derived? 2. Add to shallow-derive (option A) (option A) Adding while as a derived expression 3. Add the translation procedure: while->iteration-expression… (while (> n 0) (begin (set! x (+ x n)) (set! n (- n 1)))) (while (> n 0) (begin (set! x (+ x n)) (set! n (- n 1)))) (letrec ((iter (lambda () (if (> n 0) (begin (begin (set! x (+ x n)) (set! n (- n 1))) (iter)) ‘done)))) (iter)) (letrec ((iter (lambda () (if (> n 0) (begin (begin (set! x (+ x n)) (set! n (- n 1))) (iter)) ‘done)))) (iter)) Any problem with the solution above?There might be if iter is a predefined procedure! 13 Imperative Programming Evaluator: Adding while expressions (while (> (iter n) 0) (set! n (- n (iter n)))) (while (> (iter n) 0) (set! n (- n (iter n)))) (letrec ((iter (lambda () (if (> (iter n) 0) (begin (set! n (- n (iter n)))) (iter)) ‘done)))) (iter)) (letrec ((iter (lambda () (if (> (iter n) 0) (begin (set! n (- n (iter n)))) (iter)) ‘done)))) (iter))

3. Add the translation procedure: while->iteration-expression… Second try: (while (> (iter n) 0) (set! n (- n (iter n)))) (while (> (iter n) 0) (set! n (- n (iter n)))) (let ( (pred (lambda () (set! n (- n (iter n))))) (body (lambda () (> (iter n) 0))) ) (letrec ((iter (lambda () ( if (pred) (begin (body) (iter)) 'ok)))) (iter))) (let ( (pred (lambda () (set! n (- n (iter n))))) (body (lambda () (> (iter n) 0))) ) (letrec ((iter (lambda () ( if (pred) (begin (body) (iter)) 'ok)))) (iter))) 14 (option A) (option A) Adding while as a derived expression Imperative Programming Evaluator: Adding while expressions

The translation procedure: (define while->iteration-expression (lambda (exp) (let ((pred (make-lambda ‘() (list (while-pred exp)))) (body (make-lambda ‘() (list (while-body exp))))) derive (derive (make-let (list (list ‘body body) (list ‘pred pred)) list (list (make-letrec (list (list 'iter (make-lambda (list) (list (make-if (make-application ‘pred (list) ) (make-begin (list (make-application ‘body (list)) (make-application 'iter (list)))) '(quote ok)))))) list (list (make-application 'iter (list)))))))))) (define while->iteration-expression (lambda (exp) (let ((pred (make-lambda ‘() (list (while-pred exp)))) (body (make-lambda ‘() (list (while-body exp))))) derive (derive (make-let (list (list ‘body body) (list ‘pred pred)) list (list (make-letrec (list (list 'iter (make-lambda (list) (list (make-if (make-application ‘pred (list) ) (make-begin (list (make-application ‘body (list)) (make-application 'iter (list)))) '(quote ok)))))) list (list (make-application 'iter (list)))))))))) 15 (option A) (option A) Adding while as a derived expression We construct a let exp which is a derived exp itself. The body of a let exp / letrec exp may include several expressions (just as the body of a lambda exp). Therefore, the body argument for Make-let, make-letrec, is wrapped within a list. Imperative Programming Evaluator: Adding while expressions

(define special-form? (lambda (exp) (while? exp) (or (quoted? exp) (lambda? exp) (definition? exp) (if? exp) (begin? exp) (while? exp)))) (define special-form? (lambda (exp) (while? exp) (or (quoted? exp) (lambda? exp) (definition? exp) (if? exp) (begin? exp) (while? exp)))) (define eval-special-form (lambda (exp env) ((while? exp) (eval-while exp env)) (cond …((while? exp) (eval-while exp env))))) (define eval-special-form (lambda (exp env) ((while? exp) (eval-while exp env)) (cond …((while? exp) (eval-while exp env))))) 1. Add to special-form?. 2. Add an eval-special-form procedure (option B) (option B) Adding while as a special form 3. Add an eval-while procedure (define eval-while (lambda (exp env) (let ( (pred (while-pred exp)) (body (while-body exp))) (letrec ( (iter (lambda () (if (env-eval pred env) (begin (env-eval body env) (iter)) 'ok)))) (iter)))) (define eval-while (lambda (exp env) (let ( (pred (while-pred exp)) (body (while-body exp))) (letrec ( (iter (lambda () (if (env-eval pred env) (begin (env-eval body env) (iter)) 'ok)))) (iter)))) 16 Imperative Programming Evaluator: Adding while expressions

(define analyze-special-form (lambda (exp) (cond …((while? exp) (analyze-while exp))))) (define analyze-special-form (lambda (exp) (cond …((while? exp) (analyze-while exp))))) (define analyze-while (lambda (exp) (let ( (pred (analyze (while-pred exp))) (body (analyze (while-body exp)))) (lambda (env) (letrec ((iter (lambda() (if (pred env) (begin (body env) (iter)) 'ok)))) (iter))))) (define analyze-while (lambda (exp) (let ( (pred (analyze (while-pred exp))) (body (analyze (while-body exp)))) (lambda (env) (letrec ((iter (lambda() (if (pred env) (begin (body env) (iter)) 'ok)))) (iter))))) 1. Add to analyze-special-form 2. Add an analysis procedure: (option B) (option B) Adding while as a special form 17 Adding while to the compiler as a special form: The eval-while code has been translated to an analyzer code according to two simple rules: 1.Recursive application of analyze to the components of the expression. 2.Currying to produce a procedure that is ready for execution once an environment is given. Imperative Programming Evaluator: Adding while expressions

(define eval-while (lambda (exp env) (let ( (pred (while-pred exp)) (body (while-body exp))) (if (env-eval pred env) (begin (env-eval body env) (eval-while exp env)) 'ok)))) (define eval-while (lambda (exp env) (let ( (pred (while-pred exp)) (body (while-body exp))) (if (env-eval pred env) (begin (env-eval body env) (eval-while exp env)) 'ok)))) 18 Not every evaluation procedure can be adjusted to the analyzer by the rules of Recursive application of analyze to the expression components and currying. The following code will correctly evaluate while expressions but cannot be adjusted to the analyzer by the rules noted above: This code cannot be translated to an analyzer code by the above two rules: It involves a recursive call to eval-while which is performed during runtime. Analysis is performed during static time. Imperative Programming Evaluator: Adding while expressions