-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexercise-4.20.scm
46 lines (44 loc) · 1.58 KB
/
exercise-4.20.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
;; Exercise 4.20
(define (letrec? exp) (tagged-list? exp 'letrec))
(define (letrec-bindings exp) (cadr exp))
(define (letrec-body exp) (cddr exp))
(define (binding-vars bindings)
(map car bindings))
(define (binding-exps bindings)
(map cadr bindings))
(define (initialize vars)
(map (lambda (var) (list var '*unassigned*)) vars))
(define (transform-body body vars exps)
(if (null? vars)
body
(cons (list 'set! (car vars) (car exps))
(transform-body body (cdr vars) (cdr exps)))))
(define (transform-letrec exp)
(let ((vars (binding-vars (letrec-bindings exp)))
(expressions (binding-exps (letrec-bindings exp))))
(cons 'let
(cons (initialize vars)
(transform-body (letrec-body exp) vars expressions)))))
;; tests
(define (test4-20)
(define expression
'(letrec ((fact (lambda (n)
(if (= n 1) 1 (* n (fact (- n 1)))))))
(fact 10)))
(define target
'(let ((fact *unassigned*))
(set! fact (lambda (n) (if (= n 1) 1 (* n (fact (- n 1))))))
(fact 10)))
(equal? (transform-letrec expression) target))
;; b - Louis's definition
(let ((even? (lambda (n) (if (= n 0) true (odd? (- n 1)))))
(odd? (lambda (n) (if (= n 0) false (even? (- n 1))))))
(even? 10))
;; which reduces to
((lambda (even? odd?)
(even? 10))
(lambda (n) (if (= n 0) true (odd? (- n 1))))
(lambda (n) (if (= n 0) false (even? (- n 1)))))
;; Because the bodies of even and odd are defined outside of the
;; scope of the lambda which represents our let form, their
;; internal calls to each other have no referents.