問題4.10

;; しょうもない変更だが、let式を変更する。
(let ((a b)
      (c d)
      (e f)))

;; ->
(let (a b
      c d
      e f))

;; とかけるようにしよう。

(define (let->combination exp)
  (let ((second (cadr exp)))
    (let ((named? (symbol? second)))
      (let ((bindings (if named? (caddr exp) second))
            (body (if named? (cdddr exp) (cddr exp))))
        (let ((vars (let iter ((lst bindings) (acc '()))
                      (if (null? lst)
                          (reverse acc)
                          (iter (cddr lst) (cons (car lst) acc)))))
              (exps (let iter ((lst (cdr bindings)) (acc '()))
                      (if (null? (cdr lst))
                          (reverse (cons (car lst) acc))
                          (iter (cddr lst) (cons (car lst) acc))))))
          (if named?
              (list 'let bindings
                    (append (list 'define (append (list second) vars))
                            body)
                    (append (list second) vars))
              (append (list (append (list 'lambda vars) (cddr exp))) exps)))))))

(let->combination
 '(let (a 0
        b 1
        c 2)
    (+ a b c)))

;; -> ((lambda (a b c) (+ a b c)) 0 1 2)
;; ok