Another option would be to unwind all lets and lambdas
so each body only can contain one expression, such that (let () 1 (define two 2) two) => (let () 1 (let ()
(two 2) two))
Gambit follows R5RS, where internal defines are required to
be at the beginning of a lambda body (which a let body really is)
and where those defines are equivalent to a letrec. So the
following prints #t: (let () (define (myeven? x) (cond ((zero? x) #t) ((< x 0) (myodd? (+ x 1))) (else (myodd? (- x 1))))) (define (myodd? x) (cond ((zero? x) #f) ((< x 0) (myeven? (+ x 1))) (else (myeven? (- x 1))))) (display (myodd? 3)) (newline)) and is equivalent to (let () (letrec ((myeven? (lambda (x) (cond ((zero? x) #t) ((< x 0) (myodd? (+ x 1))) (else (myodd? (- x 1)))))) (myodd? (lambda (x) (cond ((zero? x) #f) ((< x 0) (myeven? (+ x 1))) (else (myeven? (- x 1))))))) (display (myodd? 3)) (newline))) Your transformation would mean that the binding of odd?
would not be visible to the definition of even?: Loading (let () (define (myeven? x) (cond ((zero? x) #t) ((< x 0) (myodd? (+ x 1))) (else (myodd? (- x 1))))) (let () (define (myodd? x) (cond ((zero? x) #f) ((< x 0) (myeven? (+ x 1))) (else (myeven? (- x 1))))) (let () (display (myodd? 3)) (let () (newline))))) gives frying-pan:~> gsi crap.scm *** ERROR IN myeven?, "crap.scm"@5.14 -- Unbound variable:
myodd? I believe that systems that allow interleaving expressions
and definitions interpret a body using something called letrec*
semantics, but since I'm not clear what that entails, someone else
will need to explain it. Brad