Download presentation
Presentation is loading. Please wait.
Published byJoy joyce Bayless Modified over 9 years ago
1
Assignments and Procs w/Params EOPL3 Chapter 4
2
Expressible vs. Denotable values Expressible Values –the language can express and compute these –represented in the language's syntax as expressions Denotable Values –represented in syntax by declarations –the names and their values saved within a data structure (called a namespace or environment or symbol table or activation record) In some languages, these two are not equal. Booleans are expressible in (early) FORTRAN, but not denotable. Functions are denotable in many languages, but are not expressible. In (functional subset of) Scheme, both value spaces are identical. In (full) Scheme, variable references (pointers) are denotable but not expressible. CS784(PM)2
3
Assignment, LHS := RHS l-value: left-, location, address, reference, … r-value: right-, int, real, address, … env and store allow one to describe the semantics of assignment in a purely functional style. (DENOTATIONAL SEMANTICS) Object language structures are mapped to similar Scheme structures. (META- CIRCULAR INTERPRETER) CS784(PM)3
4
Sharing sharing/aliasing Point p = new Point(); Point q = p; call by reference void f(Point p){…}; f(q); CS784(PM)4
5
Side-effects in Scheme Update variable: (set! var exp) denotes location denotes value In Scheme locations are denotable, but not expressible Sequencing: –(begin exp1 exp2 … expn) –Ordering of expressions important CS784(PM)5
6
Local Binding: let (let proc-id ([id init-expr]...) body...+)let Defines a local procedure. Evaluates the init-exprs; these become arguments to the proc. The ids must be distinct. (let fac ([n 10]) (if (zero? n) 1 (* n (fac (sub1 n))))) 3628800 CS784(PM)6
7
Local Binding: let* (let* ([id val-expr]...) body...+)let* Similar to let, but evaluates the val-exprs one by one, creating a location for each id as soon as the value is available. The ids are bound in the remaining val-exprs as well as the bodys, and the ids need not be distinct; later bindings shadow earlier bindings.let 1.(let* ([x 1] 2. [y (+ x 1)]) 3. (list y x)) (2 1) CS784(PM)7
8
Local Binding: letrec (letrec ([id val-expr]...) body...+)letrec Similar to let, but the locations for all ids are created first and filled with #, and all ids are bound in all val-exprs as well as the bodys. The ids must be distinct. 1.(letrec ((a b) (b 34)(c (+ b 5))) 2. (list a b c)) (# 34 39) 3.(letrec ([is-even? (lambda (n) 4. (or (zero? n) 5. (is-odd? (sub1 n))))] 6. [is-odd? (lambda (n) 7. (and (not (zero? n)) 8. (is-even? (sub1 n))))]) 9. (is-odd? 11)) #t CS784(PM)8
9
Comparison: let, let*, letrec (let/let*/letrec ((v1 e1 ) (v2 e2 )…(vn en )) body ) let no vi is created until all ei are evaluated. none of ei can refer to any vi let* e1 is evaluated; v1 created, bound to e1; e2 is evaluated; v2 created, bound to e2; …; ej can refer to earlier vi, i < j. letrec vi are created with #undefined as their value. with the above in effect, e1, …, en are evaluated l-to-r each vi is now bound to ei CS784(PM)9
10
Simulating Scheme letrec (letrec ((v1 exp1) (v2 exp2)) exp) ;; exp1 and exp2 are lambda-forms (let ((v1 ’*) (v2 ’*)) (set! v1 exp1) (set! v2 exp2) exp ) CS784(PM)10
11
Env and Store For functional subset, it is sufficient to model env as a function from ids to values. For imperative programming that has both assignment and sharing, separating env and store is necessary. –env: identifier location –store: location value –assignment: location X value X store store CS784(PM)11
12
EXPLICIT-REFS ExpVal = Int + Bool + Proc + Ref(ExpVal) DenVal = ExpVal –Ref(ExpVal) == references to locations that contain expressed values. newref: allocates a new location, returns a ref to it. deref: dereferences setref: changes the contents This gives a clear account of –allocation, dereferencing, and mutation CS784(PM)12
13
Even and Odd Redone let x = newref(0) in letrec even(dummy)= if zero?(deref(x)) then 1 elsebegin setref(x, -(deref(x),1)); (odd 888) end odd(dummy)= if zero?(deref(x)) then 0 elsebegin setref(x, -(deref(x),1)); (even 888) end in begin setref(x,13); (odd 888) end CS784(PM)13
14
Hidden State let g = let counter = newref(0) in proc (dummy) begin setref(counter,-(deref(counter),-1)); deref(counter) end in let a = (g 11) in let b = (g 11) in -(a,b) CS784(PM)14
15
environment for g CS784(PM)15
16
Store-Passing Specifications [c = v]σ location c is mapped to v in store σ (value-of exp1 ρ σ0) = (val1, σ1) specification for diff-exp (value-of exp1 ρ σ0) = (val1, σ1) and (value-of exp2 ρ σ1) = (val2, σ2) implies (value-of (diff-exp exp1 exp2) ρ σ0) = ( [val1] – [val2], σ2) (caution: [] incorrect symbols) CS784(PM)16
17
conditional Let (value-of e1 ρ σ0) = (v1, σ1). Then (value-of (if-exp e1 e2 e3) ρ σ0) = (value-of e2 ρ σ1) if (expval->bool v1) = #t = (value-of e3 ρ σ1) if (expval->bool v1) = #f CS784(PM)17
18
newref, deref, and setref Expression ::= newref (Expression) AST: newref-exp (exp1) Expression ::= deref (Expression) AST: deref-exp (exp1) Expression ::= setref (Expression, Expression) AST: setref-exp (exp1 exp2) CS784(PM)18
19
Specs of newref Given: –(value-of exp ρ σ0) = (val, σ1), lc ! ∈ dom(σ1 ) (value-of (newref-exp exp) ρ σ0) = ((ref-val lc), [lc=val] σ1) newref-exp evaluates its operand. Allocates a new location lc and stores val in that location. Then it returns a reference to a location lc that is new. This means that the new loc is not already in the domain of σ1. CS784(PM)19
20
Specs of deref Given: (value-of exp ρ σ0) = (lc, σ1) (value-of (deref-exp exp) ρ σ0) = (σ1(lc), σ1) exp evaluation leaves the store in state σ1. The value of that argument should be a reference to a location lc. The deref-exp then returns the contents of lc in σ1, without any further change to the store. CS784(PM)20
21
spec of setref Given: (value-of exp1 ρ σ0) = (lc, σ1) (value-of exp2 ρ σ1) = (val, σ2);; note σ1 σ2 order Then: (value-of (setref-exp exp1 exp2) ρ σ0) = ( [23], [lc = val] σ2);; caution [] setref-exp evaluates exp1 first, exp2 second. First value must be a reference to a location lc. setref-exp then updates σ2 by putting val in location lc. It could return anything; e.g. 23. This expression is executed for its effect, not its value. CS784(PM)21
22
Implementation state σ of the store as a Scheme value –represent the store as a list of expressed values, keep the state in a single global variable all the procedures of the impl have access. This representation is extremely inefficient. CS784(PM)22
23
A naive model of the store 1/3 (define empty-store (lambda () ’())) (define the-store ’uninitialized); initially (define get-store (lambda () the-store)) (define initialize-store! (lambda () (set! the-store (empty-store)))) CS784(PM)23
24
A naive model of the store 2/3 (define reference? (lambda (v) (integer? v))) (define newref (lambda (val) (let ((next-ref (length the-store))) (set! the-store (append the-store (list val))) next-ref))) (define deref (lambda (ref) (list-ref the-store ref))) CS784(PM)24
25
A naive model of the store 3/3 (define setref! (lambda (ref val) (set! the-store (letrec ((setref-inner usage: returns a list like store1, except that position ref1 contains val. (lambda (store1 ref1) (cond ((null? store1) (report-invalid-reference ref the-store)) ((zero? ref1) (cons val (cdr store1))) (else (cons (car store1) (setref-inner (cdr store1) (- ref1 1)))))))) (setref-inner the-store ref))))) CS784(PM)25
26
value-of-program (define value-of-program (lambda (pgm) (initialize-store!) (cases program pgm (a-program (exp1) (value-of exp1 (init-env)))))) CS784(PM)26
27
value-of clauses explicit-ref ops (newref-exp (exp1) (let ((v1 (value-of exp1 env))) (ref-val (newref v1)))) (deref-exp (exp1) (let ((v1 (value-of exp1 env))) (let ((ref1 (expval->ref v1))) (deref ref1)))) (setref-exp (exp1 exp2) (let ((ref (expval->ref (value-of exp1 env)))) (let ((val2 (value-of exp2 env))) (begin (setref! ref val2) (num-val 23))))) CS784(PM)27
28
IMPLICIT-REFS ExpVal = Int + Bool + Proc –references are no longer expressed values. DenVal = Ref(ExpVal) Locations are created with each binding operation: –at each procedure call, let, or letrec. –This design is called call-by-value, or implicit references. Expression ::= set Identifier = Expression –AST: assign-exp (var exp1) –Assignment statement Variables are mutable. CS784(PM)28
29
IMPLICIT-REFS examples let x = 0 in letrec even(dummy) = if zero?(x) then 1 else begin set x = --(x,1); (odd 888) end odd(dummy) = if zero?(x) then 0 else begin set x = --(x,1); (even 888) end let g = let count = 0 in proc (dummy) begin set count = --(count,--1); count end in let a = (g 11) in let b = (g 11) in --(a,b) CS784(PM)29
30
value-of specs (value-of (var-exp var) ρ σ) = ( σ(ρ(var)), σ) –environment ρ binds variables to locations Given: (value-of exp1 ρ σ0) = (val1, σ1) Then, (value-of (assign-exp var exp1) ρ σ0) = ( [27], [ρ(var) = val1] σ1);; caution: [] For procedure call, the rule becomes (apply-procedure (procedure var body ρ) val σ) = (value-of body [var = lc]ρ [lc = val]σ ) CS784(PM)30
31
MUTABLE-PAIRS A Language with Mutable Pairs Reading Assignment CS784(PM)31
32
Parameter-Passing Variations When a procedure body is executed, –its formal parameter is bound to a denoted value. –It must be passed from the actual argument in the call. Natural parameter passing –the denoted value is the same as the expressed value of the actual parameter (EOPL3 page 75). Call-by-value –the denoted value is a reference to a location containing the expressed value of the actual parameter (EOPL3 section 4.3). CS784(PM)32
33
call-by-value v. -by-ref Under call-by-value, a new reference is created for every evaluation of an operand Under call-by-reference, a new reference is created for every evaluation of an operand other than a variable. CS784(PM)33
34
CALL-BY-REFERENCE let p = proc (x) set x = 4 in let a = 3 in begin (p a); a end let f = proc (x) set x = 44 in let g = proc (y) (f y) in let z = 55 in begin (g z); z end next prog: 11 versus --11 let swap = proc (x) proc (y) let temp = x inbegin set x = y; set y = temp end in let a = 33 in let b = 44 inbegin ((swap a) b); --(a,b) end CS784(PM)34
35
call-by-reference ExpVal = Int + Bool + Proc DenVal =Ref(ExpVal) a new location is created for every evaluation of an operand other than a variable. CS784(PM)35
36
call-by-ref implementation (define apply-procedure (lambda (proc1 val) (cases proc proc1 (procedure (var body saved- env) (value-of body (extend-env var val saved-env)))))) (call-exp (rator rand) (let ((proc (expval->proc (value-of rator env))) (arg (value-of- operand rand env))) (apply-procedure proc arg))) CS784(PM)36
37
value-of-operand (define value-of-operand (lambda (exp env) (cases expression exp (var-exp (var) (apply-env env var)) (else (newref (value-of exp env)))))) CS784(PM)37
38
variable aliasing let b = 3 in let p = proc (x) proc(y) begin set x = 4; y end in ((p b) b) both x and y refer to the same location Yields 4 aliasing makes it difficult to understand programs. CS784(PM)38
39
Lazy Evaluation Under lazy evaluation, an operand in a procedure call is not evaluated until it is needed by the procedure body. Sometimes in a given call a procedure never evaluates some of its formal parameters. This can potentially avoid non-termination. letrec infinite-loop (x) = infinite-loop(--(x, --1)) in let f = proc (z) 11 in (f (infinite-loop 0)) infinite-loop does not terminate. above prog returns 11 under lazy eval CS784(PM)39
40
Lazy Evaluation Terms A thunk is a procedure with no arguments. One can delay (perhaps indefinitely) the evaluation of an operand by encapsulating it as a thunk. Freezing: forming thunks Thawing: evaluating thunks CS784(PM)40
41
call-by-name, -by-need call-by-name: invoke the thunk every time the parameter is referred to. –In the absence of side effects this is a waste of time, since the same value is returned each time. call-by-need: record the value of each thunk the first time it is invoked, and thereafter refers to the saved value. –an example of memoization. CS784(PM)41
42
CALL-BY-NAME An operand is frozen when it is passed unevaluated to the procedure Operand is thawed when procedure evaluates it DenVal = Ref(ExpVal + Thunk) ExpVal = Int + Bool + Proc (define-datatype thunk thunk? (a-thunk (exp1 expression?) (env environment?))) CS784(PM)42
43
value-of-operand (define value-of-operand (lambda (exp env) (cases expression exp (var-exp (var) (apply-env env var)) (else (newref (a-thunk exp env)))))) CS784(PM)43
44
call by name design CS784(PM)44 (var-exp (var) (let ((ref1 (apply-env env var))) (let ((w (deref ref1))) (if (expval? w) w (value-of-thunk w)))))
45
value-of-thunk: Thunk→ExpVal (define value-of-thunk (lambda (th) (cases thunk th (a-thunk (exp1 saved-env) (value-of exp1 saved-env)))) CS784(PM)45
46
call by need Alternatively, once we find the value of the thunk, we can install that expressed value in the same location, so that the thunk will not be evaluated again. This is an instance of a general strategy called memoization. CS784(PM)46
47
memoization CS784(PM)47 (var-exp (var) (let ((ref1 (apply-env env var))) (let ((w (deref ref1))) (if (expval? w) w (let ((val1 (value-of-thunk w))) (begin (setref! ref1 val1) val1))))))
48
Lazy Evaluation Summary In the absence of (side) effects, it supports reasoning about programs in a particularly simple way. The effect of a procedure call can be modeled by replacing the call with the body of the procedure, with every reference to a formal parameter in the body replaced by the corresponding operand. This evaluation strategy is the basis for the lambda calculus, where it is called β-reduction. Unfortunately, call-by-name and call-by-need make it difficult to determine the order of evaluation, which in turn is essential to understanding a program with effects. Thus lazy evaluation is popular in functional programming languages (those with no effects), and rarely found elsewhere. CS784(PM)48
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.