In using `sum` as in section 1.3.1,
it seems terribly awkward to have to declare trivial
functions
such as
`pi_term` and `pi_next` just
so we can use them as arguments to our higher-order
function.
Rather than declare `pi_next` and
`pi_term`, it would be more convenient
to have a way to directly specify the
function that returns its
input incremented by 4

and the
function that returns the
reciprocal of its input times its input plus 2.

We can do this by
introducing *function definition expressions*, which create functions.
Using function definitions, we can describe what we want as

x => x + 4;

x => 1.0 / (x * (x + 2));

Then our
`pi_sum`
function
can be expressed without
declaring any auxiliary functions
as

function pi_sum(a,b) { return sum(x => 1.0 / (x * (x + 2)), a, x => x + 4, b); }

Again using
a function definition,
we can write the `integral`
function
without having to
declare the auxiliary function
`add_dx`:

function integral(f, a, b, dx) { return sum(f, a + dx / 2.0, x => x + dx, b) * dx; }

The resulting function is just as much a function as one that is created using a function declaration statement. The only difference is that it has not been associated with any name in the environment. In fact,

function plus4(x) { return x + 4; }

const plus4 = x => x + 4;

// read x => x + 4 // as: ^ ^ ^ ^ ^ // function with argument x that results in the value plus 4

Like any expression that has a function as its value, a function definition expression can be used as the function expression in an application combination such as

((x, y, z) => x + y + square(z))(1, 2, 3);

Another use of function definitions is in creating local names. We often need local names in our functions other than those that have been bound as parameters. For example, suppose we wish to compute the function \[ f(x,y)=x(1+xy)^2 +y(1-y)+(1+xy)(1-y)\] which we could also express as \begin{eqnarray*} a &=& 1+xy\\ b &=& 1-y\\ f(x,y) &=& xa^2 +yb +ab \end{eqnarray*} In writing a function to compute $f$, we would like to include as local names not only $x$ and $y$ but also the names of intermediate quantities like $a$ and $b$. One way to accomplish this is to use an auxiliary function to bind the local names:

function f(x, y) { function f_helper(a, b) { return x * square(a) + y * b + a * b; } return f_helper(1 + x * y, 1 - y); }

Of course, we could use a
function definition
expression to specify an anonymous
function for binding our local names.
The body of
`f` then becomes a single call to that
function:

function f(x,y) { return ( (a,b) => x * square(a) + y * b + a * b )(1 + x * y, 1 - y); }

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; }

expmod(base, exp / 2, m)

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; }

function expmod(base, exp, m) { if (exp === 0) { return 1; } else { if (is_even(exp)) { const to_half = expmod(base, exp / 2, m); return to_half * to_half % m; } else { return base * expmod(base, exp - 1, m) % m; } } }

function f(g) { return g(2); }

f(square);

f(z => z * (z + 1));

[1] If there is only one parameter,
then the parentheses around the parameter list can be omitted.

[2] In section 2.2.4, we will
extend the syntax of function definition expressions to allow blocks as bodies,
as in function declaration statements.

[3] The idea to introduce functions without naming
them plays a central role in 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.

[4]
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
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.

function h() { const x = 1; function i() { const x = x + 1; return x; } return i(); } h();

1.3.2
Function Definition Expressions