4.7 Exercise 4.7

We can support let* expressions by transforming them into a series of nested let expressions (one per binding).

(define (make-let bindings . body)
  (append (list 'let bindings) body))
(define (let*->nested-lets exp)
  (define (iter bindings)
    (if (null? (cdr bindings))
        (apply make-let (cons bindings (let-body exp)))
        (make-let (list (car bindings)) (iter (cdr bindings)))))
  (if (null? (let-bindings exp))
      (let-body exp)
      (iter (let-bindings exp))))

It is fully legal to rewrite the let* expression into a series of nested let expressions and add a rule to eval that will evaluate this, as in (eval (let*->nested-lets exp) env). All that will happen is that eval will be indirected once more before ultimately simplifying to non-derived expressions and evalauting them. This is no different than how let expressions are handled now.