Lexical vs Dynamic Binding, Recursion I
Lexical vs Dynamic BindingContinued on WednesdayRecursion I
- The value of a
proc-expis a closure.where we have defined(proc-exp (ids body) (closure ids body env))closureas a kind of procval byTo implement lexical binding in procedure applications, we evaluate the body of the procedure in its environment of definition, extended by binding its formals to the values of the operands.(define-datatype procval procval? (closure (ids (list-of symbol?)) (body expression?) (env environment?)))where(app-exp (rator rands) (let ((proc (eval-expression rator env)) (args (eval-rands rands env))) (apply-procval proc args)))(define apply-procval (lambda (proc args) (cases procval proc (closure (ids body env) (eval-expression body (extend-env ids args env))) (else (error 'procval "Not a procedure ~s" proc)))))- Dynamic binding is a binding mechanism for procedure calls in which free variables in the body are evaluated in the environment of the procedure call.
Dynamic binding can be implemented by passing the current environment to apply-procval and evaluating the body in the environment obtained by extending that environment rather than the environment of definition. I.e.,
and(app-exp (rator rands) (let ((proc (eval-expression rator env)) (args (eval-rands rands env))) (apply-procval proc args env)))(define apply-procval (lambda (proc args env) (cases procval proc (closure (ids body env0) (eval-expression body (extend-env ids args env))) (else (error 'procval "Not a procedure ~s" proc)))))- Examples of lexical vs dynamic binding (Cf Ex 3.5.11,13, p82)
Cf Ex 3.5.11
Ex 3.5.13 -- illustrates difficulty in understanding behavior with dynamic binding.let a = 1 in let a = 3 in let p = proc (x) +(x, a) a = 5 in *(a, (p 2)) => ? (lexical binding) => ? (dynamic binding)Replacing formal parameter x with alet a = 1 in let a = 3 p = proc () a in let f = proc (x) (p) a = 5 in (f 2) => ? (lexical binding) => ? (dynamic binding)let a = 1 in let a = 3 p = proc () a in let f = proc (a) (p) a = 5 in (f 2) => ? (lexical binding) => ? (dynamic binding)- Recursion is easy with dynamic binding -- recursive procedures can be bound with
let. (Early Lisps used dynamic binding. Scheme was first Lisp with lexical binding, followed by Common Lisp.)What is behavior (Cf Ex 3.5.12, p 82) with lexical, dynamic binding of the following?
let fact = proc (n) add1(n) in let fact = proc (n) if zero?(n) then 1 else *(n, (fact sub1(n))) in (fact 5) => ? (lexical binding) => ? (dynamic binding)- Recursion can be simulated with lexical binding and first class functions by including an extra parameter to pass the "recursive" function.
Consider the example from p80.
What is the value of this program?let makemult = proc (maker, x) if zero?(x) then 0 else +(4, (maker maker sub1(x))) in let times4 = proc (x) (makemult makemult x) in (times4 3)A recursive function f has a definition of the form
E.g.f = proc(x) (e f x)We can abstract the body and rewrite the above definition of times4 astimes4 = proc (x) if zero?(x) then 0 else +(4, (times4 x))Ex 3.5.3, p 80 -- Write a procedure for factorial using this idealet e = proc (f, x) if zero?(x) then 0 else +(4, (f sub1(x))) in let fm = proc (m, x) (e proc(x) (m m x) x) in let times4 = proc (x) (fm fm x) in (times4 3)
- cs217d13.dl
- We introduce a
letrecsyntax to define recursive functions.will be represented in abstract syntax by the grammar[expression] ::= letrec {[letrec-decl]}* in [expression] [letrec-decl] ::= [symbol]() = [expression] | [symbol]([symbol] {, [symbol]}*) = [expression]or(expression ("letrec" (arbno id "(" (separated-list id ",") ")" "=" expression) "in" expression) letrec-exp)expressiondatatypeE.g, a recursive definition and application of times4 could be expressed(letrec-exp (proc-names (list-of symbol?)) (idss (list-of (list-of symbol?))) (bodies (list-of expression?)) (letrec-body expression?))letrec times4(x) = if zero?(x) then 0 else +(4, (times4 sub1(x))) in (times4 3)- A
letrec-expcan be evaluated withWe just need to define(letrec-exp (proc-names idss bodies letrec-body) (eval-expression letrec-body (extend-env-recursively proc-names idss bodies env)))extend-env-recursivelyto get the desired semantics.