Reputation:
In scheme you can define functions which return a lambda expression and use them to define new functions. For example, you can write this code
(define (pow-iter base exp r)
(if (= exp 1)
r
(pow-iter base (- exp 1) (* base r))))
(define (pow exp)
(lambda (base)
(pow-iter base exp base)))
(define cubic (pow 3))
(cubic 2)
We have here a function pow
which takes the exponent as argument and evaluates to a lambda function which evaluates to the nth power of the given base.
However, if we put that within a scope like this:
(define (do-cubic x)
(define (pow-iter base exp r)
(if (= exp 1)
r
(pow-iter base (- exp 1) (* base r))))
(define (pow exp)
(lambda (base)
(pow-iter base exp base)))
(define cubic (pow 3))
(cubic x))
(do-cubic 2)
I get an error
pow: undefined; cannot use before initialization
Why does this error occur and is there any way to fix it without changing the logic of the program?
Upvotes: 2
Views: 232
Reputation: 31145
This program provokes the same error:
#lang r5rs
(let ()
(define (foo x) (lambda (y) (+ 42 x)))
(define bar (foo 1))
(bar 2))
Output:
foo: undefined;
cannot use before initialization
The reason you get an error is that "internal definitions" are rewritten into a letrec
expression all the bindings are in effect while their initial values are being computed, thus allowing mutually recursive definitions.
(letrec ((foo (lambda (x) (lambda (y) (+ 42 x))))
(bar (foo 1)))
(bar 2))
In R5RS the initialization expressions are evaluated in an unspecified order. This means that in the first snippet above it is possible for (define bar (foo 1))
to be evaluated before (define (foo x) ...)
. In other words the value of foo
is needed before foo
have been initialized.
In Racket (#lang racket
) internal definitions use letrec*
-semantics (i.e. the initialization expressions are evaluated in the order they appear in the code. Thus the program runs without errors.
Note also that the letrec
in #lang racket
corresponds to what letrec*
does in "R5RS"-implementations.
For more information on letrec
vs letrec*
see the introduction of http://www.cs.indiana.edu/~dyb/pubs/letrec-reloaded.pdf
Upvotes: 2