Search code examples
scopeschemeletletrec

Why TSPL's letrec example can be run in ChezScheme with only let?


In TSPL 3.2 we find:

(letrec ((even?
          (lambda (x)
            (or (= x 0)
                (odd? (- x 1)))))
         (odd?
          (lambda (x)
            (and (not (= x 0))
                 (even? (- x 1))))))

;; (list (even? 20) (odd? 20))) => (#t #f)

but the same program, if use let instead of letrec, still can run in ChezScheme:

(let    ((even?
          (lambda (x)
            (or (= x 0)
                (odd? (- x 1)))))
         (odd?
          (lambda (x)
            (and (not (= x 0))
                 (even? (- x 1))))))

Is it a Chez's bug? TSPL can't be wrong. Thanks!


Solution

  • The built in scheme functions even? and odd? are what are being called in the bodies of the lambdas in the let version. Use different names and you'll get an error:

    (let ([my-even?
           (lambda (x)
             (or (= x 0)
                 (my-odd? (- x 1))))]
          [my-odd?
           (lambda (x)
             (and (not (= x 0))
                  (my-even? (- x 1))))])
      (list (my-even? 20) (my-odd? 20)))
    

    will fail. Change it to letrec and it'll work because your function names will then be in scope in the lambda bodies.