From: Ramakrishnan Muthukrishnan Date: Sun, 18 Dec 2011 07:15:53 +0000 (+0530) Subject: solution to 4.20 X-Git-Url: https://git.rkrishnan.org/running.html?a=commitdiff_plain;h=531e659d988a2cc4e11c89378aca766b7247f922;p=sicp.git solution to 4.20 --- diff --git a/src/sicp/ex4_20.rkt b/src/sicp/ex4_20.rkt new file mode 100644 index 0000000..17f11fe --- /dev/null +++ b/src/sicp/ex4_20.rkt @@ -0,0 +1,93 @@ +#lang racket + +#| +(define (f x) + (letrec ((even? + (lambda (n) + (if (= n 0) + #t + (odd? (- n 1))))) + (odd? + (lambda (n) + (if (= n 1) + #t + (even? (- n 1)))))) + )) + + + +(letrec ...) is transformed into: + +(let ((even? '*unassigned*) + (odd? '*unassigned*)) + (set! even? (lambda (n) + (if (= n 0) + ... + ...))) + (set! odd? (lambda (n) + ...)) + ) + +|# + +#| + +letrec is of the form: + +(letrec (( ) ... ( )) + ) + +|# +(define (tagged-list? expr tag) + (or (pair? expr) (eq? (car expr) tag))) + +(define (letrec? expr) + (tagged-list? expr 'letrec)) + +(define (letrec-variables expr) + (let ((p (car (cdr expr)))) + (map car p))) + +(define (letrec-values expr) + (let ((p (car (cdr expr)))) + (map cadr p))) + +(define (letrec->let expr) + (if (not (letrec? expr)) + (error "not a letrec expression -- LETREC") + (let ((vars (letrec-variables expr)) + (vals (letrec-values expr)) + (body (cdr (cdr expr)))) + (cons 'let + (cons (map (lambda (var) + (list var ''*unassigned*)) + vars) + (append (map (lambda (var val) + (list 'set! var val)) + vars + vals) + body)))))) + +#| + +b. In the case where we use lecrec, this gets transformed into let. So, when we call (f 5) +a new frame is formed with even? and odd? assigned to '*unassigned. Then these are set to +the lambda expressions belonging to even? and odd?. + +When we use a let in the place of letrec, a frame gets created with even? and odd? assigned +to the lambda expressions. Then the body of the let expression (i.e. ) +is wrapped in a lambda which takes as parameters, even? and odd? is called with the lambda +expressions corresponding to even? and odd?. + +i.e. ((lambda (e? o?) + ) + (lambda (n) (...reference to o?..)) + (lambda (n) (.reference to e?... ))) + +So, a frame gets created which assigns e? and o? to the corresponding lambdas. The enclosing +environment for it, does not have e? or o? defined. So, these definitions +When we draw the environment, the two lambdas passed as parameters do not see each other as their +environment is the enclosing env of t. so they are undefined. When the body is evaluated, then +these will generate error for undefined references. + +|# \ No newline at end of file