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.