Exercise 4.8

今度は名前付き let を lambda に展開する問題。

一瞬どうするの?と戸惑ったけど、具体例を書いてみると

(let foo ((a 1)
          (b 2))
       (print "abc")
       (+ 1 a b))

(lambda (a b)
   (define foo (lambda (a b)
                  (print "abc")
                  (+ 1 a b)))
   (foo 1 2))

に変換するということが分かった(変な例ですが…)ので、それをそのまま起こして、

(define (make-lambda parameters body)
  (cons 'lambda (cons parameters body)))
(define (make-let bind body)
  (cons 'let (cons bind body)))
(define (make-define name exp)
  (list 'define name exp))

(define (let->combination exp)
  (let* ((name (if (let-named? exp) (let-name exp) #f))
         (body (let-body (if name (cdr exp) exp)))
         (bind (let-bind (if name (cdr exp) exp)))
         (procedure (make-lambda (let-parameters bind) body)))
    (if name
      (cons (make-lambda (let-parameters bind)
                         (list (make-define name procedure)
                               (cons name (let-parameters bind))))
            (let-arguments bind))
      (cons procedure (let-arguments bind)))))

となった。