As opposed to definitions at the top level, which are visible in the whole program (or current module, when Guile modules are used), it is also possible to define variables which are only visible in a well-defined part of the program. Normally, this part of a program will be a procedure or a subexpression of a procedure.

With the constructs for local binding (`let`

, `let*`

and
`letrec`

), the Scheme language has a block structure like most
other programming languages since the days of Algol 60. Readers
familiar to languages like C or Java should already be used to this
concept, but the family of `let`

expressions has a few properties
which are well worth knowing.

The first local binding construct is `let`

. The other constructs
`let*`

and `letrec`

are specialized versions for usage where
using plain `let`

is a bit inconvenient.

— syntax: **let**` bindings body`

bindingshas the form((variable1init1) ...)that is zero or more two-element lists of a variable and an arbitrary expression each. All

variablenames must be distinct.A

`let`

expression is evaluated as follows.

- All
initexpressions are evaluated.- New storage is allocated for the
variables.- The values of the
initexpressions are stored into the variables.- The expressions in
bodyare evaluated in order, and the value of the last expression is returned as the value of the`let`

expression.- The storage for the
variablesis freed.The

initexpressions are not allowed to refer to any of thevariables.

— syntax: **let***` bindings body`

Similar to

`let`

, but the variable bindings are performed sequentially, that means that allinitexpression are allowed to use the variables defined on their left in the binding list.A

`let*`

expression can always be expressed with nested`let`

expressions.(let* ((a 1) (b a)) b) == (let ((a 1)) (let ((b a)) b))

— syntax: **letrec**` bindings body`

Similar to

`let`

, but it is possible to refer to thevariablefrom lambda expression created in any of theinits. That is, procedures created in theinitexpression can recursively refer to the defined variables.(letrec ((even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))) (odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))) (even? 88)) ⇒ #t

There is also an alternative form of the `let`

form, which is used
for expressing iteration. Because of the use as a looping construct,
this form (the named let) is documented in the section about
iteration (see Iteration)