Warning: This is the manual of the legacy Guile 2.2 series. You may want to read the manual of the current stable series instead.

Next: , Previous: , Up: Binding Constructs   [Contents][Index]


6.12.3 Internal definitions

A define form which appears inside the body of a lambda, let, let*, letrec, letrec* or equivalent expression is called an internal definition. An internal definition differs from a top level definition (see Top Level), because the definition is only visible inside the complete body of the enclosing form. Let us examine the following example.

(let ((frumble "froz"))
   (define banana (lambda () (apple 'peach)))
   (define apple (lambda (x) x))
   (banana))
⇒
peach

Here the enclosing form is a let, so the defines in the let-body are internal definitions. Because the scope of the internal definitions is the complete body of the let-expression, the lambda-expression which gets bound to the variable banana may refer to the variable apple, even though its definition appears lexically after the definition of banana. This is because a sequence of internal definition acts as if it were a letrec* expression.

(let ()
  (define a 1)
  (define b 2)
  (+ a b))

is equivalent to

(let ()
  (letrec* ((a 1) (b 2))
    (+ a b)))

Internal definitions are only allowed at the beginning of the body of an enclosing expression. They may not be mixed with other expressions.

Another noteworthy difference to top level definitions is that within one group of internal definitions all variable names must be distinct. That means where on the top level a second define for a given variable acts like a set!, an exception is thrown for internal definitions with duplicate bindings.

As a historical note, it used to be that internal bindings were expanded in terms of letrec, not letrec*. This was the situation for the R5RS report and before. However with the R6RS, it was recognized that sequential definition was a more intuitive expansion, as in the following case:

(let ()
  (define a 1)
  (define b (+ a a))
  (+ a b))

Guile decided to follow the R6RS in this regard, and now expands internal definitions using letrec*.


Next: , Previous: , Up: Binding Constructs   [Contents][Index]