Let Binding
A "let binding", in other languages, might be called a "variable declaration". let
binds values to names. They can be seen and referenced by code that comes after them.
RElet greeting = "hello!";
let score = 10;
let newScore = 10 + score;
#Block Scope
Bindings can be scoped through {}
.
RElet message = {
let part1 = "hello";
let part2 = "world";
part1 ++ " " ++ part2
};
/* `part1` and `part2` not accessible here! */
The value of the last line of a scope is implicitly returned.
#Design Decisions
Reason's if
, while
and functions all use the same block scoping. The code below works not because of some special "if scope"; but simply because it's the same scope syntax and feature you just saw:
REif (displayGreeting) {
let message = "Enjoying the docs so far?";
print_endline(message)
};
/* `message` not accessible here! */
#Bindings Are Immutable
Reason let bindings are "immutable", aka "cannot change/vary". This helps Reason's type system to deduce and optimize much more than other languages (and in turn, help you more).
#Binding Shadowing
The above restriction might sound unpractical at first. How are would you change a value then? Usually, 2 ways:
The first is to realize that many times, what you want isn't to mutate a variable's value. For example, in JavaScript:
JSvar result = 0;
result = calculate(result);
result = calculateSomeMore(result);
What you're really doing is just to name intermediate steps. You didn't need to mutate result
at all! You could have just written this:
JSvar result1 = 0;
var result2 = calculate(result1);
var result3 = calculateSomeMore(result2);
In Reason, this obviously works too:
RElet result1 = 0;
let result2 = calculate(result2);
let result3 = calculateSomeMore(result2);
Anyway, in Reason, we support let binding "shadowing". So you can write this too:
RElet result = 0;
let result = calculate(result);
let result = calculateSomeMore(result);
As a matter of fact, even this is fine:
RElet result = "hello";
Js.log(result); // prints "hello"
let result = 1;
Js.log(result); // prints 1
The binding you refer to is whatever's the closest upward. No mutation here! If you need real mutation, e.g. passing a value around, have it modified by many pieces of code, we provide a slightly heavier mutation feature.