recursive procedures and scopes
DESCRIPTION
Recursive Procedures and Scopes. EOPL3 Sections 3.4 - 3.7. The LETREC Language. All of PROC, plus … Concrete: Expression :: = letrec Identifier (Identifier) = Expression in Expression AST: letrec-exp (proc-name bound-var proc-body letrec-body). value of a letrec expression. - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/1.jpg)
Recursive Procedures and Scopes
EOPL3 Sections 3.4 - 3.7
![Page 2: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/2.jpg)
2
The LETREC Language
• All of PROC, plus …• Concrete:
– Expression :: = letrec Identifier (Identifier) =
Expression in Expression• AST:
– letrec-exp (proc-name bound-varproc-body letrec-body)
CS784(pm)
![Page 3: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/3.jpg)
value of a letrec expression
(value-of(letrec-exp proc-name
bound-var proc-body letrec-body)ρ)
= (value-of letrec-body(extend-env-rec proc-name
bound-var proc-body ρ))
CS784(pm) 3
![Page 4: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/4.jpg)
(extend-env-rec pnm bvar pbdy ρ)
• Let ρ1 == (extend-env-rec proc-name bound-var proc-body ρ)
• (apply-env ρ1 proc-name)= (proc-val
(procedure bound-var proc-body ρ1))
• (apply-env ρ1 var) = (apply-env ρ var)
CS784(pm) 4
![Page 5: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/5.jpg)
environment datatype(define-datatype environment environment?
(empty-env)(extend-env(var identifier?)(val expval?)(env environment?))(extend-env-rec(p-name identifier?)(b-var identifier?)(body expression?)(env environment?)))
CS784(pm) 5
![Page 6: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/6.jpg)
apply-env(define apply-env (lambda (env search-var)
(cases environment env(empty-env () (report-no-binding-found search-var))(extend-env (saved-var saved-val saved-env) (if (eqv? saved-var search-var)saved-val(apply-env saved-env search-var)))(extend-env-rec (p-name b-var p-body saved-env) (if (eqv? search-var p-name)(proc-val (procedure b-var p-body env))(apply-env saved-env search-var))))))
CS784(pm) 6
![Page 7: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/7.jpg)
7
Exercise 3.35• “The representations we have seen so far are inefficient, because they
build a new closure every time the procedure is retrieved. But the closure is the same every time. We can build the closures only once, by putting the value in a vector of length 1 and building an explicit circular structure, like …”
• .
CS784(pm)
![Page 8: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/8.jpg)
Exercise 3.35: extend-env-rec
(define extend-env-rec(lambda (p-name b-var body saved-env)(let ((vec (make-vector 1)))(let ((new-env (extend-env p-name vec saved-env)))(vector-set! vec 0(proc-val (procedure b-var body new-env)))new-env))))
CS784(pm) 8
![Page 9: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/9.jpg)
Scoping and Binding
• references– (f x y)– f, x, and y
• declarations– (lambda (x) (+ x 3))– (let ((x (+ y 7))) (+ x 3))
• y, and second x are refs• first x is a declaration
• lexical scoping rulesCS784(pm) 9
![Page 10: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/10.jpg)
Kinds of Scope• Static or Lexical scope
– determined by structure of program– Scheme, C++, Java, and many compiled languages
• Dynamic scope– determined by path of execution– Lisp dialects, Perl, and many interpreted languages
• Global Scope– File scope
• Local Scope– Block
• Body of a procedure• Body of a loop
• Scope alters the meaning
CS784(pm) 10
![Page 11: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/11.jpg)
CS784(pm) 11
proc main()int x := 5; proc q() { x := x + 1;}
proc r() {int x := 0;
q(); }{ r(); print(x); }.
Scoping : Free (non-local) Variables• Static scoping x -> xoutput: 6
• Dynamic scoping
x -> xoutput: 5
![Page 12: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/12.jpg)
CS784(pm) 12
let x = 15in let f = proc () x in ( let x = 8 in (f) ) + (f)
Static Scoping x -> x 30Dynamic Scoping x -> x 23 x -> x
![Page 13: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/13.jpg)
Fig 3.13 Contour diagram
CS784(pm) 13
![Page 14: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/14.jpg)
Figure 3.14 Contour diagram
CS784(pm) 14
![Page 15: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/15.jpg)
Binding Rules1. A variable declared by a proc is bound when the procedure is
applied. – (apply-procedure (procedure var body ρ) val)
= (value-of body (extend-env var val ρ))2. A let-variable is bound by the value of its right-hand side.
– (value-of (let-exp var val body) ρ)= (value-of body (extend-env var val ρ))
3. A variable declared by a letrec is bound using its right-hand side as well.
– (value-of (letrec-exp proc-namebound-var proc-body letrec-body) ρ)
= (value-of letrec-body (extend-env-rec proc-namebound-var proc-body ρ))
CS784(pm) 15
![Page 16: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/16.jpg)
lexical depth# of contours crossed
(lambda (x)(
(lambda (a)(x a))
x))
zero-based indexing
(nameless-lambda(
(nameless-lambda(#1 #0))
#0))
CS784(pm) 16
![Page 17: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/17.jpg)
The Translator
• Source: var-exp, let-exp, …• Target: nameless-var-exp, nameless-let-exp• translation-of: handles expressions• translation-of-program: handles programs.• translation-of-program runs translation-of
in a suitable initial static environment.
CS784(pm) 17
![Page 18: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/18.jpg)
translation-of-program
(define translation-of-program(lambda (pgm)(cases program pgm(a-program (exp1)(a-program (translation-of exp1 (init-senv)))))))
(define init-senv (lambda ()(extend-senv ’i(extend-senv ’v(extend-senv ’x(empty-senv))))))
CS784(pm) 18
![Page 19: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/19.jpg)
Fg 3.16 lexical-address translator(define translation-of
(lambda (exp senv) (cases expression exp(const-exp (num) (const-exp num))(diff-exp (exp1 exp2)(diff-exp(translation-of exp1 senv)(translation-of exp2 senv)))… altogether 8 cases …(else(report-invalid-source-expression exp)) )))
CS784(pm) 19
![Page 20: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/20.jpg)
20
translation-of zero?-exp
(zero?-exp (exp1)(zero?-exp
(translation-of exp1 senv)))
CS784(pm)
![Page 21: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/21.jpg)
translation-of if-exp
(if-exp (exp1 exp2 exp3)(if-exp
(translation-of exp1 senv)(translation-of exp2 senv)(translation-of exp3 senv)))
CS784(pm) 21
![Page 22: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/22.jpg)
translation-of var-exp
(var-exp (var)(nameless-var-exp(apply-senv senv var)))
CS784(pm) 22
![Page 23: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/23.jpg)
translation-of let-exp
(let-exp (var exp1 body)(nameless-let-exp
(translation-of exp1 senv)(translation-of body
(extend-senv var senv))))
CS784(pm) 23
![Page 24: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/24.jpg)
translation-of proc-exp
(proc-exp (var body)(nameless-proc-exp
(translation-of body(extend-senv var
senv))))
CS784(pm) 24
![Page 25: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/25.jpg)
translation-of call-exp
(call-exp (rator rand)(call-exp
(translation-of rator senv)(translation-of rand senv)))
CS784(pm) 25
![Page 26: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/26.jpg)
Our top-level procedure
(define run(lambda (string)
(value-of-program(translation-of-program
(scan&parse string)))))
CS784(pm) 26
![Page 27: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/27.jpg)
nameless environments• nameless-environment? : SchemeVal → Bool• empty-nameless-env : () → Nameless-env• extend-nameless-env : Expval × Nameless-env → Nameless-env• apply-nameless-env : Nameless-env × Lexaddr → DenVal
• (apply-procedure (procedure var body ρ) val)= (value-of body (extend-env var val ρ)) page 79
• (apply-procedure (procedure body ρ) val)= (value-of body (extend-nameless-env val ρ)) page 98
CS784(pm) 27
![Page 28: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/28.jpg)
procedure datatype
(define-datatype proc proc?(procedure
(body expression?)(saved-nameless-env
nameless-environment?)))
CS784(pm) 28
![Page 29: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/29.jpg)
apply-procedure
(define apply-procedure(lambda (pc val)
(cases proc pc (procedure (body saved-nameless-
env)(value-of body
(extend-nameless-env val saved-nameless-
env))))))CS784(pm) 29
![Page 30: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/30.jpg)
redefine value-of(define value-of
(lambda (exp nameless-env)(cases expression exp(const-exp (num) ...as before...)(diff-exp (exp1 exp2) ...as before...)(zero?-exp (exp1) ...as before...)(if-exp (exp1 exp2 exp3) ...as before...)(call-exp (rator rand) ...as before...)… next slide …(else (report-invalid-translated-expression exp)))))
CS784(pm) 30
![Page 31: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/31.jpg)
redefine value-of
(nameless-var-exp (n)(apply-nameless-env nameless-env n))
(nameless-let-exp (exp1 body)(let ((val (value-of exp1 nameless-env)))
(value-of body(extend-nameless-env val nameless-env))))
(nameless-proc-exp (body)(proc-val
(procedure body nameless-env)))
CS784(pm) 31
![Page 32: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/32.jpg)
value-of-program
(define value-of-program(lambda (pgm)
(cases program pgm(a-program (exp1)
(value-of exp1(init-nameless-
env))))))
CS784(pm) 32
![Page 33: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/33.jpg)
extra slide if time permits
• ========================================================================================================================================================================================================================================================
CS784(pm) 33
![Page 34: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/34.jpg)
34
Procedure Invocations• Dynamic scoping(define (eval-expression exp env) (cases expression exp (app-exp (rator rands) . . . (let ((proc (eval-expression rator env)) (args (eval-rands rands env))) (if (procval? proc) (apply-procval proc args env) (eopl:error 'eval-expression "Applying non-procedure ~s" proc) )))
CS784(pm)
![Page 35: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/35.jpg)
35
Processing Procedure Invocations
• Dynamic scoping• (define (apply-procval proc args c-env)
(cases procval proc (procv (ids body) (eval-expression body (extend-env ids args c-env)) )))
CS784(pm)
![Page 36: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/36.jpg)
36
Processing Procedure Invocations
>(run "let x = 1 inlet f = proc () x in(f)")
1>(run "let x = 1 in
let f = proc (x) x in (f 2)")2Static scoping>(run "let x = 1 in
let f = proc () xx = 5in (f)")
1Dynamic scoping>(run "let x = 1 in
let f = proc () x x = 5in (f)")
5
CS784(pm)
![Page 37: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/37.jpg)
37
Implementing Dynamic Scoping
• The value of variable x is the last value bound to x. => stack discipline– Deep binding
• Use a global stack for all variables– Shallow binding
• Use a separate stack for each variable• Implementing recursion is trivial.• Meaning of a call depends on the context.CS784(pm)
![Page 38: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/38.jpg)
Lexical Scope Pros and Cons
• Scope of names is known to the compiler.• Permits type checking by compiler• Easily check for uninitialized variables• Easier to analyze program correctness• Recursion is harder to implement
CS784(pm) 38
![Page 39: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/39.jpg)
Dynamic Scope Pros and Cons• Meaning of variables known only at run-time.
– Cannot perform type checking before execution– Programs are flexible, but harder to understand
• Easy to implement recursion• Renaming in the caller can effect the semantics of a program
– Locality of formals destroyed.– if renamed parameter now captures a free variable in the called
function. – Recall the interpretation of a free variable in a function body can
change based on the context (environment) of a call.
CS784(pm) 39
![Page 40: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/40.jpg)
Dyn Binding Can be DifficultExercise 3.29: … dynamic binding may be exceptionally difficult to understand.
For example, under lexical binding, consistently renaming the bound variables of a procedure can never change the behavior of a program: we can even remove all variables and replace them by their lexical addresses, as in section 3.6. But under dynamic binding, this transformation is unsafe.
For example, under dynamic binding, the procedure proc (z) a returns the value of the variable a in its caller’s environment. Thus, the program
let a = 3in let p = proc (z) a
in let f = proc (x) (p 0) in let a = 5 in (f 2)
returns 5, since a’s value at the call site is 5. What if f’s formal parameter were a?
CS784(pm) 40
![Page 41: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/41.jpg)
41
Application of Dynamic Scoping
• Exception Handling– provide a separate construct in statically scoped
language• Setting Local Formatting Parameters• Input-Output Redirection
– avoids passing parameters explicitly through “intermediate” procedures
CS784(pm)
![Page 42: Recursive Procedures and Scopes](https://reader034.vdocuments.site/reader034/viewer/2022052312/56816335550346895dd3c08a/html5/thumbnails/42.jpg)
Dyn Binding Can be Powerful
• Exercise 3.37 With dynamic binding, recursive procedures may be bound by let; no special mechanism is necessary for recursion. Test the following
let fact = proc (n) add1(n)in let fact = proc (n) if zero?(n) then 1 else *(n,(fact -
(n,1)))in (fact 5)
using both lexical and dynamic binding.CS784(pm) 42