(r5rs.info.gz) Binding constructs
Info Catalog
(r5rs.info.gz) Conditional
(r5rs.info.gz) Derived expression types
(r5rs.info.gz) Sequencing
4.2.2 Binding constructs
------------------------
The three binding constructs `let', `let*', and `letrec' give Scheme a
block structure, like Algol 60. The syntax of the three constructs is
identical, but they differ in the regions they establish for their
variable bindings. In a `let' expression, the initial values are
computed before any of the variables become bound; in a `let*'
expression, the bindings and evaluations are performed sequentially;
while in a `letrec' expression, all the bindings are in effect while
their initial values are being computed, thus allowing mutually
recursive definitions.
-- library syntax: let <bindings> <body>
_Syntax:_ <Bindings> should have the form
((<variable1> <init1>) ...,),
where each <init> is an expression, and <body> should be a
sequence of one or more expressions. It is an error for a
<variable> to appear more than once in the list of variables being
bound.
_Semantics:_ The <init>s are evaluated in the current environment
(in some unspecified order), the <variable>s are bound to fresh
locations holding the results, the <body> is evaluated in the
extended environment, and the value(s) of the last expression of
<body> is(are) returned. Each binding of a <variable> has <body>
as its region.
(let ((x 2) (y 3))
(* x y)) ==> 6
(let ((x 2) (y 3))
(let ((x 7)
(z (+ x y)))
(* z x))) ==> 35
See also named `let', section Iteration.
-- library syntax: let* <bindings> <body>
_Syntax:_ <Bindings> should have the form
((<variable1> <init1>) ...,),
and <body> should be a sequence of one or more expressions.
_Semantics:_ `Let*' is similar to `let', but the bindings are
performed sequentially from left to right, and the region of a
binding indicated by `(<variable> <init>)' is that part of the
`let*' expression to the right of the binding. Thus the second
binding is done in an environment in which the first binding is
visible, and so on.
(let ((x 2) (y 3))
(let* ((x 7)
(z (+ x y)))
(* z x))) ==> 70
-- library syntax: letrec <bindings> <body>
_Syntax:_ <Bindings> should have the form
((<variable1> <init1>) ...,),
and <body> should be a sequence of one or more expressions. It is
an error for a <variable> to appear more than once in the list of
variables being bound.
_Semantics:_ The <variable>s are bound to fresh locations holding
undefined values, the <init>s are evaluated in the resulting
environment (in some unspecified order), each <variable> is
assigned to the result of the corresponding <init>, the <body> is
evaluated in the resulting environment, and the value(s) of the
last expression in <body> is(are) returned. Each binding of a
<variable> has the entire `letrec' expression as its region,
making it possible to define mutually recursive procedures.
(letrec ((even?
(lambda (n)
(if (zero? n)
#t
(odd? (- n 1)))))
(odd?
(lambda (n)
(if (zero? n)
#f
(even? (- n 1))))))
(even? 88))
==> #t
One restriction on `letrec' is very important: it must be possible
to evaluate each <init> without assigning or referring to the
value of any <variable>. If this restriction is violated, then it
is an error. The restriction is necessary because Scheme passes
arguments by value rather than by name. In the most common uses
of `letrec', all the <init>s are lambda expressions and the
restriction is satisfied automatically.
Info Catalog
(r5rs.info.gz) Conditional
(r5rs.info.gz) Derived expression types
(r5rs.info.gz) Sequencing
automatically generated byinfo2html