Exercise 4.7
今度は let* 式を等価の let 式に変形する問題
(define (make-let bind body) (cons 'let (cons bind body))) (define (let-parameters exp) (map car (car exp))) (define (let-arguments exp) (map cadr (car exp))) (define (let-bind exp) (cadr exp)) (define (let-body exp) (cddr exp)) (define (let-first-bind exp) (car exp)) (define (let-rest-bind exp) (cdr exp)) (define (let*->nested-lets exp) (let*->nested-lets-iter (let-bind exp) (let-body exp))) (define (let*->nested-lets-iter bind body) (make-let (list (let-first-bind bind)) (if (null? (let-rest-bind bind)) body (list (let*->nested-lets-iter (let-rest-bind bind) body)))))
実際に動かしてみて
gosh> (let*->nested-lets '(let* ((x 3) (y (+ x 2))) (+ x y) (* x y))) (let ((x 3)) (let ((y (+ x 2))) (+ x y) (* x y)))
となるので、let式への展開は OK。
ただし、これをさらに Exercise 4.6 で作成した let->combination で lambda まで展開させた場合、
(let->combination (let*->nested-lets '(let* ((x 3) (y (+ x 2))) (+ x y) (* x y)))) ((lambda (x) (let ((y (+ x 2))) (+ x y) (* x y))) 3)
と、一番外側の let しか展開されないので、そのまま評価器の eval に乗せることはできない。