## Local binding constructs

The binding constructs `let`, `let*`, `letrec`, and `letrec*` give Scheme a block structure, like Algol 60. The syntax of these four 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 `letrec` and `letrec*` expressions, all the bindings are in effect while their initial values are being computed, thus allowing mutually recursive definitions.

Syntax: `let` `((```pattern`` ``init```)` `...``)` ``body``

> Declare new local variables as found in the `pattern`s. Each `pattern` is matched against the corresponding `init`. The `init`s are evaluated in the current environment (in left-to-right onder), the `variable`s in the `patterns`s are bound to fresh locations holding the matched results, the `body` is evaluated in the extended environment, and the values of the last expression of body 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

> An example with a non-trivial pattern:

>     (let (([a::double b::integer] (vector 4 5)))
>       (cons b a))  ⇒ (5 . 4.0)

Syntax: `let*` `((```pattern`` `init``)` `...``)` ``body``

> The `let*` binding construct is similar to `let`, but the bindings are performed sequentially from left to right, and the region of a `variable`s in a `pattern` is that part of the `let*` expression to the right of the `pattern`. Thus the second pattern is matched in an environment in which the bindings from the first pattern are visible, and so on.

>     (let ((x 2) (y 3))
>       (let* ((x 7)
>              (z (+ x y)))
>         (* z x)))  ⇒ 70

Syntax: `letrec` `((``variable` [`::` ``type``] `init``)` `...``)` ``body``

Syntax: `letrec*` `((``variable` [`::` ``type``] `init``)` `...``)` ``body``

> The `variable`s are bound to fresh locations, each `variable` is assigned in left-to-right order to the result of the corresponding `init`, the `body` is evaluated in the resulting environment, and the values of the last expression in body are returned. Despite the left-to-right evaluation and assignment order, each binding of a `variable` has the entire `letrec` or `letrec*` expression as its region, making it possible to define mutually recursive procedures.

> In Kawa `letrec` is defined as the same as `letrec*`. In standard Scheme the order of evaluation of the `init`s is undefined, as is the order of assignments. If the order matters, you should use `letrec*`.

> If it is not possible to evaluate each `init` without assigning or referring to the value of the corresponding `variable` or the variables that follow it, it is an error.

>     (letrec ((even?
>               (lambda (n)
>                 (if (zero? n)
>                     #t
>                     (odd? (- n 1)))))
>              (odd?
>               (lambda (n)
>                 (if (zero? n)
>                     #f
>                     (even? (- n 1))))))
>       (even? 88))
>          ⇒ #t