1 / 20

Implementing Recursion

Implementing Recursion. Recap: Goals. Experimenting with PL design alternatives Scoping, parameter passing, arrays, ... Runnable prototype of reference implementation. Cf. Informal description of a programming problem with an example executable for reference. Recap: closure.

alton
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

  2. Recap: Goals • Experimenting with PL design alternatives Scoping, parameter passing, arrays, ... • Runnable prototype of reference implementation. • Cf. Informal description of a programming problem with an example executable for reference.

  3. Recap: closure • procedure definition • bind a closure to proc name. • closure == (formals, body, creation-environment)

  4. let insufficient for recursion • Consider, in the defined language (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!

  5. “Correct” Environment : Circularity Old approach

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

  7. letrec 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);

  8. Three 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)

  9. 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.

  10. (define eval-expression (lambda (exp env) (cases expression exp … (primapp-exp (prim rands) … ) (app-exp (ratorrands) (let ((proc (eval-expression ratorenv)) (args (eval-randsrandsenv))) (if (procval? proc) (apply-procval proc args) (eopl:error 'eval-expression “Applying non-procedure ~s" proc)) (proc-exp (ids body) (closure idsbodyenv)) (let-exp (ids rands body) (let ((args (eval-randsrandsenv))) (eval-expression body (extend-envidsargsenv)))) (letrec-exp (proc-names idss bodies letrec-body) (eval-expression letrec-body (extend-env-recursively proc-namesidssbodiesenv))) )))

  11. Extended recursive environment TBD • A list of the variables in the procdecls that is created by mapping the selector function for variables from a procdecl onto the list of procedure declarations. • A vector containing procedure records (not closures) created from the formals and body of each procedure in the procedure declarations. • The active environment.

  12. 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?)) )

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

  14. (cont’d) (define (apply-envenv sym) (cases environment env (empty-env-record () (eopl:error 'empty-env “Unbound ~s" sym)) (extended-env-record (symsvals 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)))) ))

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

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

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

  18. 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 )

  19. 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))))

  20. (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)))) )))

More Related