(let n 12) => let n = 12;
(let res (square a)) => let res = a*a;
(let mod3 (eq 0 (% i 3))) => let mod3 = (0 == i % 3); (let ((a 1)
(b 2))
(+ a b))
It's closer to the ML version of let, which works like this: let
val a = 1
val b = 2
in
a + b
end
You can sequence expressions for side effects, as well. (let ((a 1)
(b 2))
(incf a)
(do-it a b)
(+ a b))The scope is clearly not defined by the parentheses, and I've been programming in Common Lisp for 25 years, so I'm pretty used to Lisp syntax.
A sibling comment suggests it comes from the JavaScript let (which did not exist when I learned JavaScript; it wasn't introduced until 1.7), which is scoped to the containing lexical block, rather than a block introduced by the let form itself.
(It's possible some language other than LISP was the first to use let, but my suspicion is it was LISP.)
Playing with it, the binding is scoped to the entire block, but the assignment happens in statement order so that e.g. the following will be an error, rather than logging either "1" or "2" both of which there could be arguments for:
{
let x = 1;
{
console.log(x);
let x = 2;
}
}