solution to 4.20
authorRamakrishnan Muthukrishnan <vu3rdd@gmail.com>
Sun, 18 Dec 2011 07:15:53 +0000 (12:45 +0530)
committerRamakrishnan Muthukrishnan <vu3rdd@gmail.com>
Sun, 18 Dec 2011 07:15:53 +0000 (12:45 +0530)
src/sicp/ex4_20.rkt [new file with mode: 0644]

diff --git a/src/sicp/ex4_20.rkt b/src/sicp/ex4_20.rkt
new file mode 100644 (file)
index 0000000..17f11fe
--- /dev/null
@@ -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))))))
+    <body>))
+
+
+
+(letrec ...) is transformed into:
+
+(let ((even? '*unassigned*)
+      (odd? '*unassigned*))
+  (set! even? (lambda (n)
+                (if (= n 0)
+                    ...
+                    ...)))
+  (set! odd? (lambda (n)
+               ...))
+  <body>)
+
+|#
+
+#|
+
+letrec is of the form:
+
+(letrec ((<var1> <exp1>) ... (<varn> <expn>))
+  <body>)
+
+|#
+(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. <rest of body of f>)
+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?)
+       <rest of body of f>) 
+      (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