3.1 Solution for Exercise 3

(define-syntax-rule (iflet x e1 e2 e3)
  (let ([tmp e1])
    (if tmp
        (let ([x tmp]) e2)
        e3)))

The following version is wrong, because it puts e3 in the scope of x:

; WRONG
(define-syntax-rule (iflet x e1 e2 e3)
  (let ([x e1])
    (if x e2 e3)))

An alternative is to “freeze” e3 outside of the let-binding of x and then “thaw” it inside:

; OKAY
(define-syntax-rule (iflet x e1 e2 e3)
  (let ([thunk3 (lambda () e3)])
    (let ([x e1])
      (if x e2 (thunk3)))))

Don’t be afraid to use lambda to control the environment and evaluation order of an expression. In code such as this, the Racket compiler can inline the call to thunk3; that lambda costs nothing at run time.