 Cs784(Prasad)L10Rec1 Implementing Recursion. cs784(Prasad)L10Rec2 let insufficient for recursion ( (let((fact(lambda (n) (if (zero? n) 1 (* n (fact (-

Presentation on theme: "Cs784(Prasad)L10Rec1 Implementing Recursion. cs784(Prasad)L10Rec2 let insufficient for recursion ( (let((fact(lambda (n) (if (zero? n) 1 (* n (fact (-"— Presentation transcript:

cs784(Prasad)L10Rec2 let insufficient for recursion ( (let((fact(lambda (n) (if (zero? n) 1 (* n (fact (- n 1))) ) ) )) (fact 6) ) Problem : The closure to be formed must freeze the environment containing the “correct” binding for fact which is the closure itself!

cs784(Prasad)L10Rec3 “Correct” Environment : Circularity Old approach

cs784(Prasad)L10Rec4 Concrete syntax ::= letrec * in ::= () | ( {, }*) ::= = Abstract Syntax letrec-exp (proc-names idss bodies letrec-body)

cs784(Prasad)L10Rec5 Example letrec even(x) = if zero?(x) then 1 else (odd sub1(x)) odd(x) = if zero?(x) then 0 else (even sub1(x)) in (odd 13);

cs784(Prasad)L10Rec6 Potential Approaches Delay the creation of the closure until a suitable environment has been formed. Create the environment and then change what one of its procedure binding points to. Simulate letrec using let and assignment in the object language, or alternatively, using assignment in the meta- language. Create the closure with a “hole” and then “install” the final environment, when available, later. Refer to EOPL (1st Ed., Chapter 7)

cs784(Prasad)L10Rec7 Delayed Closure Creation (New Env.) So far, each procedure definition is translated as a closure ( ), and the environment binds a closure to proc name. To handle (mutually) recursive procedures, the creation of the closure is delayed until the binding for the proc name is required (using apply-env ), prior to carrying out apply-proc.

cs784(Prasad)L10Rec8 (define eval-expression (lambda (exp env) (cases expression exp... (primapp-exp (prim rands) … ) (app-exp (rator rands) (let ((proc (eval-expression rator env)) (args (eval-rands rands env))) (if (procval? proc) (apply-procval proc args) (eopl:error 'eval-expression “Applying non-procedure ~s" proc)) (proc-exp (ids body) (closure ids body env)) (let-exp (ids rands body) (let ((args (eval-rands rands env))) (eval-expression body (extend-env ids args env))) ) (letrec-exp (proc-names idss bodies letrec-body) (eval-expression letrec-body (extend-env-recursively proc-names idss bodies env))) )))

cs784(Prasad)L10Rec9 (define-datatype environment environment? (empty-env-record) (extended-env-record (syms (list-of symbol?)) (vals vector?) (env environment?)) (recursively-extended-env-record (proc-names (list-of symbol?)) (idss (list-of (list-of symbol?))) (bodies (list-of expression?)) (env environment?)) ) Extended Recursive Environments

cs784(Prasad)L10Rec10 (define (empty-env) (empty-env-record)) (define (extend-env syms vals env) (extended-env-record syms (list->vector vals) env)) (define (extend-env-recursively proc-names idss bodies old-env) (recursively-extended-env-record proc-names idss bodies old-env)) (cont’d)

cs784(Prasad)L10Rec11 (define (apply-env env sym) (cases environment env (empty-env-record () (eopl:error 'empty-env “Unbound ~s" sym)) (extended-env-record (syms vals old-env) (let ((pos (rib-find-position sym syms))) (if (number? pos) (vector-ref vals pos) (apply-env old-env sym)))) (recursively-extended-env-record (proc-names idss bodies old-env) (let ((pos (rib-find-position sym proc- names))) (if (number? pos) (closure (list-ref idss pos) (list-ref bodies pos) env) (apply-env old-env sym)))) )) (cont’d)

cs784(Prasad)L10Rec12 Example let x = 6 in let y = 8 in letrec p = D1 q = D2 in let z = 10 in (p) INIT-ENV : [] EXT-ENV: [x = 6,[]] EXT-ENV: [y=8, [x = 6,[]]] REC-EXT-ENV: [{p=D1,q=D2}+[y=8, [x = 6,[]]] EXT-ENV: [z=10, [{p=D1,q=D2}+[y=8, [x = 6,[]]] ] Closure: D1%[{p=D1,q=D2}+[y=8, [x = 6,[]]]

cs784(Prasad)L10Rec13 Another Implementation (based on procedures) (define environment? procedure?) (define (apply-env env sym) (env sym)) (define (empty-env) (lambda (sym) (eopl:error 'empty-env “Unbound ~s" sym))) (define (extend-env ids vals env) (lambda (sym) (let ((pos (rib-find-position sym ids))) (if (number? pos) (list-ref vals pos) (apply-env env sym))) ))

cs784(Prasad)L10Rec14 (cont’d) (define (extend-env-recursively proc-names idss bodies old-env) (letrec ((rec-env (lambda (sym) (let((pos( rib-find-position sym proc-names ))) (if (number? pos) (closure (list-ref idss pos) (list-ref bodies pos) rec-env) (apply-env old-env sym)))) )) rec-env) )

cs784(Prasad)L10Rec15 Simulating letrec using let and assignment (letrec ((var1 exp1) (var2 exp2)) exp ) (* exp1 and exp2 are lambda -forms *) (let ((var1 ’*) (var2 ’*)) (set! var1 exp1) (set! var2 exp2) exp )

cs784(Prasad)L10Rec16 Yet Another Implementation (based on assignment) (define (extend-env-recursively proc-names idss bodies old-env) (let ((len (length proc-names))) (let ((vec (make-vector len))) (let ((env (extended-env-record proc-names vec old-env))) (for-each (lambda (pos ids body) (vector-set! vec pos (closure ids body env))) (iota len) idss bodies) env))))

cs784(Prasad)L10Rec17 (cont’d) (define apply-env (lambda (env sym) (cases environment env (empty-env-record () (eopl:error 'empty-env “Unbound ~s" sym)) (extended-env-record (syms vals old-env) (let ((pos (rib-find-position sym syms))) (if (number? pos) (vector-ref vals pos) (apply-env old-env sym)))) )))

Download ppt "Cs784(Prasad)L10Rec1 Implementing Recursion. cs784(Prasad)L10Rec2 let insufficient for recursion ( (let((fact(lambda (n) (if (zero? n) 1 (* n (fact (-"

Similar presentations