# Let Expression

Matt Bierner edited this page Apr 9, 2014 · 9 revisions

The let expression binds variables in an expression, and can be used wherever an expression may appear.

``````2 + let a = 3 in a * 10; // 32
``````

The body of the let expression captures as much as possible to its right, and let expressions are right associative:

``````let a = 3 in let b = 4 in a + b;
// is the same as
let a = 3 in (let b = 4 in a + b);
``````

### Multiple Bindings

Multiple values can be bound in a single let expression. Bound values are evaluated left to right and previously bound values can be used in the current binding:

``````// These are the same
let a = 3, b = 5 in a + b;
let a = 3 in let b = 5 in a + b;

// Using an existing binding.
let a = 3, b = a + 10 in a + b;
let a = 3 in let b = a + 10 in a + b;

// Rebinding a value using existing value
let a = 3, a = a + 5 in a; // 8
``````

### Capture

Let expressions capture as much as possible to their right.

``````4 * let a = 2 in a + 3;
4 * (let a = 2 in a + 3); // 20
4 * (2 + 3);
``````

Capture can be limited by wrapping the entire expression in parentheses:

``````4 * (let a = 2 in a) + 3;
4 * 2 + 3; // 11
``````

### Unpacks

Let expression bindings may use any unpack pattern on their left hand side:

``````let
o#{x, y} = {'a': 3, 'x': 6, 'z': 5, 'y': 8},
[first] = [1, 2, 3]
in
first + y + x + o.a; // 18
``````

### Scope and Evaluation

Let expressions introduce a new scope for the bindings and body. Bindings may hide existing bindings for the duration of the expression. Use of let expression bindings outside of the expression is not valid.

``````var a = 14
let a = 3 in a * a; // 9
``````

Bound values will only be evaluated once no matter how many times they are used. Evaluation is in-order, left to right.

### Recursive Bindings

Recursive bindings allow a binding to access itself in its value. This is only useful when the value is a function. Recursive bindings use the `:=` operator in place of `=`.

``````// Normal binding. This is an error since `fib` in undefined in the function body.
let
fib = \x -> ?x < 2 :x :(fib(n - 1) + fib(n - 2))
in
fib(10);

// Using a recursive binding fixes this
let
fib := \x -> ?x < 2 :x :(fib(n - 1) + fib(n - 2))
in
fib(10);
``````

Named functions can always access themselves by function name. The scope of the function name is limited to the evaluation of the bound value.

``````let fib = function impl \x -> ?x < 2 :x :(impl(x - 1) + impl(x - 2)) in
fib(10);
``````
##### Clone this wiki locally
You can’t perform that action at this time.
Press h to open a hovercard with more details.