-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsection-4.1.6.rkt
105 lines (91 loc) · 2.94 KB
/
section-4.1.6.rkt
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#lang sicp
; ex 4.16
;
; Install in make-procedure. Otherwisw it has to be transformed everytime it's
; called.
(define (scan-out-defines body)
(define (separate body def expr)
(cond ((null? body) (cons def expr))
((definition? (car body))
(separate (cdr body) (append def (list (car body))) expr))
(else (separate (cdr body) def (append expr (list (car body)))))))
(let* ((p (separate body '() '()))
(def (car p))
(expr (cdr p)))
; It's crucial to return body as is if it contains no definition instead of
; transforming it (let () <body>), or it will cause infinite loop.
(if (null? def)
body
(list
(make-let
(map (lambda (d) (list (definition-variable d) '*unassigned*)) def)
(append
(map
(lambda (d)
(make-assignment (definition-variable d) (definition-value d)))
def)
expr))))))
(define (lookup-variable-value var env)
(define (env-loop env)
(if (eq? env the-empty-environment)
(error "Unbound variable" var)
(let* ([frame (first-frame env)]
[pair (scan var frame)])
(if pair
(if (eq? (cdr pair) '*unassigned*)
(error "Unbound variable" var)
(cdr pair))
(env-loop (enclosing-environment env))))))
(env-loop env))
; ex 4.17
;
; The body of a lambda expression is transformed into a let expression, which
; is transformed into another lambda expression, which, when called, creates a
; new frame.
;
; Maybe treat let as a special form instead of transforming it into lambda.
; ex 4.18
;
; I don't think the implementation in the text and the one in the ex
; have much difference. They are both going to work or not to work. In
; this case, I think neither of them works because stream-map will
; evaluate y, when y is still '*unassigned*.
; TODO ex 4.19
;
; Huh, I never thought that Scheme's (also Racket's) internal
; definition is actually bound simultaneously. What are the advantages
; over sequential bingind? And what other languages have this feature?
; ex 4.20
;
; If you want to define variables that are based on other variables,
; let won't work.
(define (letrec? exp) (tagged-list? exp 'letrec))
(define (letrec->let exp)
(make-let
(map (lambda (b) (list (car b) '*unassigned*)) (let-bindings exp))
(append
(map (lambda (b) (make-assignment (car b) (cadr b))) (let-bindings exp))
(let-body exp))))
; ex 4.21
;
; What the hell is this...
(define (fib m)
((lambda (n)
((lambda (f) (f f n))
(lambda (g k)
(cond ((= k 0) 0)
((= k 1) 1)
(else (+ (g g (- k 1))
(g g (- k 2))))))))
m))
(define (f x)
((lambda (even? odd?)
(even? even? odd? x))
(lambda (ev? od? n)
(if (= n 0)
true
(od? ev? od? (- n 1))))
(lambda (ev? od? n)
(if (= n 0)
false
(ev? ev? od? (- n 1))))))