Names that are declared with const inside of function declarations have the surrounding block as their scope.[3] We have seen that it is often useful to declare names that are local to function declarations. When functions become big, it will contribute to their readability if we keep the scope of the names as narrow as possible. Consider for example expmod in exercise 1.26 in section 1.2.6.
function expmod(base, exp, m) {
return exp === 0
? 1
: is_even(exp)
? expmod(base, exp / 2, m)
* expmod(base, exp / 2, m)
% m
: base
* expmod(base, exp - 1, m)
% m;
}


This function is unnecessarily inefficient, because it contains two identical calls:
expmod(base, exp / 2, m)


While this can be easily fixed in this example using the square function, this is not so easy in general. Without using square, we would be tempted to introduce a local name for the expression as follows:
function expmod(base, exp, m) {
const to_half = expmod(base, exp / 2, m);
return exp === 0
? 1
: is_even(exp)
? to_half * to_half
% m
: base
* expmod(base, exp - 1, m)
% m;
}


This would make the function not just inefficient, but actually non-terminating! The problem is that the constant declaration appears outside the conditional expression, which means that it is executed even when the base case exp === 0 is reached. To avoid this situation, we shall provide for conditional statements, and allow for return statements to appear in several branches of the statement. Using a conditional statement, the function expmod can be written as follows:
function expmod(base, exp, m) {
if (exp === 0) {
return 1;
} else {
if (is_even(exp)) {
const to_half = expmod(base, exp / 2, m);
} else {
return base * expmod(base, exp - 1, m) % m;
}
}
}


The general form of a conditional statement is if ($\textit{predicate}$) { $\textit{consequent}$ } else { $\textit{alternative}$ } and, like conditional expressions, their evaluation first evaluates the $\textit{predicate}$. If it evaluates to true, the interpreter evaluates the $\textit{consequent}$ statements and otherwise the $\textit{alternative}$ statements. Note that any constant declarations occurring in either part are local to that part, because both are enclosed in curly braces and thus form their own block.
[1] If there is only one parameter, then the parentheses around the parameter list can be omitted. In section 2.2.4, we will extend the syntax of lambda expressions to allow blocks as bodies, as in function declaration statements.
[2] It would be clearer and less intimidating to people learning JavaScript if a term more obvious than lambda expression, such as function definition were used. But the convention is very firmly entrenched, not just for Lisp and Scheme but also for JavaScript, Java and other languages, no doubt partly due to the influence of the Scheme editions of this textbook. The notation is adopted from the $\lambda$ calculus, a mathematical formalism introduced by the mathematical logician Alonzo Church (1941). Church developed the $\lambda$ calculus to provide a rigorous foundation for studying the notions of function and function application. The $\lambda$ calculus has become a basic tool for mathematical investigations of the semantics of programming languages. Note that the JavaScript parser requires parentheses around the lambda expression in this case.
[3] Note that a name declared in a function using const cannot be used before the declaration fully is evaluated, not even in the right-hand expression of the declaration itself, and regardless whether the same name is declared outside of the function. Thus the program
function h() {
const x = 1;
function i() {
const x = x + 1;
return x;
}
return i();
}
h();


leads to an error, because the x in x + 1 is used before its declaration is fully evaluated. The const declaration makes sure that the declared name is not used before the evaluation of the declaration is complete. We will return to this issue in section 4.1.6, after we learn more about evaluation.
1.3.2 Constructing Functions using Lambda Expressions