1 / 17

Implementing Recursion

Implementing Recursion. let insufficient for recursion. (let ( ( fact ( lambda (n) (if (zero? n) 1 ( * n ( fact (- n 1)) ) ) ) ) ) (fact 6) )

elaine-hart
Download Presentation

Implementing Recursion

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Implementing Recursion L10Rec

  2. 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! L10Rec

  3. “Correct” Environment : Circularity Old approach L10Rec

  4. Concrete syntax <expression> ::= letrec <procdecl>* in <expression> <idlist> ::= () | (<identifier> {, <identifier>}*) <procdecl> ::= <identifier> <idlist> = <expression> • Abstract Syntax letrec-exp (proc-names idss bodies letrec-body) L10Rec

  5. 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); L10Rec

  6. 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) L10Rec

  7. Delayed Closure Creation (New Env.) • So far, each procedure definition is translated as a closure (< formals, body, creation-time-environment >), 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. L10Rec

  8. (define eval-expression (lambda (exp env) (cases expression exp ... (primapp-exp (prim rands) … ) (app-exp (rator rands) (let ((proc (eval-expression ratorenv)) (args (eval-rands randsenv))) (if (procval? proc) (apply-procval proc args) (eopl:error 'eval-expression “Applying non-procedure ~s" proc)) (proc-exp (ids body) (closure idsbody 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-namesidssbodies env))) ))) L10Rec

  9. Extended Recursive Environments (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?)) ) L10Rec

  10. (cont’d) (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)) L10Rec

  11. (cont’d) (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)))) )) L10Rec

  12. 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,[]]] ] Example Closure: D1%[{p=D1,q=D2}+[y=8, [x = 6,[]]] L10Rec

  13. 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))) )) L10Rec

  14. (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) ) L10Rec

  15. 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 ) L10Rec

  16. 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)))) L10Rec

  17. (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)))) ))) L10Rec

More Related