[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
6.12.2 Local Variable Bindings
As opposed to definitions at the top level, which creates bindings that are visible to all code in a module, 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*
,
letrec
, 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 most basic local binding construct is let
.
- syntax: let bindings body
bindings has the form
((variable1 init1) …)
that is zero or more two-element lists of a variable and an arbitrary expression each. All variable names must be distinct.
A
let
expression is evaluated as follows.- All init expressions are evaluated.
- New storage is allocated for the variables.
- The values of the init expressions are stored into the variables.
-
The expressions in body are evaluated in order, and the value of
the last expression is returned as the value of the
let
expression.
The init expressions are not allowed to refer to any of the variables.
The other binding constructs are variations on the same theme: making new values, binding them to variables, and executing a body in that new, extended lexical context.
- syntax: let* bindings body
Similar to
let
, but the variable bindings are performed sequentially, that means that all init expression are allowed to use the variables defined on their left in the binding list.A
let*
expression can always be expressed with nestedlet
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 the variable from lambda expression created in any of the inits. That is, procedures created in the init expression 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
Note that while the init expressions may refer to the new variables, they may not access their values. For example, making the
even?
function above creates a closure (see section The Concept of Closure) referencing theodd?
variable. Butodd?
can’t be called until after execution has entered the body.
- syntax: letrec* bindings body
Similar to
letrec
, except the init expressions are bound to their variables in order.letrec*
thus relaxes the letrec restriction, in that later init expressions may refer to the values of previously bound variables.(letrec ((a 42) (b (+ a 10))) ;; Illegal access (* a b)) ;; The behavior of the expression above is unspecified (letrec* ((a 42) (b (+ a 10))) (* a b)) ⇒ 2184
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 section Iteration)
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on April 20, 2013 using texi2html 5.0.