The function `sqrt` is our first example of a process defined by a set of
mutually
defined functions.
Notice that the
declaration of `sqrt_iter` is
*recursive*; that is, the
function
is defined in
terms of itself. The idea of being able to define a
function
in
terms of itself may be disturbing; it may seem unclear how such a
circular

definition could make sense at all, much less specify a
well-defined process to be carried out by a computer. This will be
addressed more carefully in
section 1.2. But first let's consider
some other important points illustrated by the
`sqrt` example.

Observe that the problem of computing square roots breaks up naturally
into a number of subproblems: how to tell whether a guess is good
enough, how to improve a guess, and so on. Each of these tasks is
accomplished by a separate
function.
The entire `sqrt` program
can be viewed as a cluster of
functions
(shown in
Figure 1.2) that mirrors the
decomposition of the problem into subproblems.

The importance of this decomposition strategy is not simply that one
is dividing the program into parts. After all, we could take any
large program and divide it into parts—the first ten lines, the next
ten lines, the next ten lines, and so on. Rather, it is crucial that
each
function
accomplishes an identifiable task that can be used as a
module in defining other
functions.
For example, when we
define the
`good_enough` function
in terms of `square`, we are able to
regard the `square`
function
as a
black box.

We are not at
that moment concerned with *how* the
function
computes its
result, only with the fact *that* it computes the square. The details
of how the square is computed can be suppressed, to be considered at a
later time. Indeed, as far as the
`good_enough` function
is
concerned, `square` is not quite a
function
but rather an
abstraction of a
function,
a so-called
*functional abstraction*.
At this level of abstraction, any
function
that computes the square
is equally good.

Thus, considering only the values they return, the following two functions squaring a number should be indistinguishable. Each takes a numerical argument and produces the square of that number as the value.[1]

function square(x) { return x * x; }

function square(x) { return math_exp(double(math_log(x))); } function double(x) { return x + x; }

So a function should be able to suppress detail. The users of the function may not have written the function themselves, but may have obtained it from another programmer as a black box. A user should not need to know how the function is implemented in order to use it.

One detail of a function's implementation that should not matter to the user of the function is the implementer's choice of names for the function's parameters. Thus, the following functions should not be distinguishable:

function square(x) { return x * x; }

function square(y) { return y * y; }

This principle—that the meaning of a
function
should be independent
of the parameter names used by its author—seems on the
surface to be
self-evident, but its consequences are profound. The simplest
consequence is that the parameter names of a
function
must be local
to the body of the
function.
For example, we used
`square`
in the declaration of
`good_enough`
in our square-root
function
:

function good_enough(guess, x) { return abs(square(guess) - x) < 0.001; }

The intention of the author of
`good_enough`
is to determine if
the square of the first argument is within a given tolerance of
the second argument. We see that the author of
`good_enough`
used
the name `guess` to refer to the
first argument and `x` to
refer to the second argument. The argument of
`square` is
`guess`. If the author of
`square` used
`x` (as above)
to refer to that argument, we see that the
`x` in
`good_enough`
must be a different `x` than the one
in `square`.
Running the
function
`square` must
not affect the value
of `x` that is used by
`good_enough`,
because that value of
`x` may be needed by
`good_enough`
after `square` is done
computing.

If the parameters were not local to the bodies of their respective
functions,
then the parameter `x` in
`square` could be
confused with the parameter `x` in
`good_enough`,
and the
behavior of
`good_enough`
would depend upon which version of
`square` we used. Thus,
`square` would not be the black box
we desired.

A parameter of a
function
has a very special role in the
function declaration,
in that it doesn't matter what name the
parameter
has. Such a name is called
*bound*, and we
say that the function declaration
*binds* its
parameters.
The meaning of a
function declaration is unchanged if a bound name
is consistently renamed throughout the
declaration.[2]
If a name
is not bound, we say that it is
*free*. The
set of expressions for which a binding
declares
a name
is called the
*scope* of that name.
In a
function declaration, the bound names
declared as the
parameters of the
function
have the body of
the
function
as their scope.

In the declaration of `good_enough` above,
`guess` and `x` are
bound names but `abs`, and
`square` are free.
The meaning of `good_enough`
should be independent of the names we
choose for `guess` and `x`
so long as they are distinct and
different from `abs`, and
`square`. (If we renamed
`guess` to
`abs` we would have introduced a bug by
*capturing*
the name `abs`.
It would have changed from free to bound.) The
meaning of `good_enough` is
not independent of the choice of its
free names, however. It surely depends upon the fact (external to
this declaration) that the symbol `abs` names a
function for computing the absolute value of a number.
The JavaScript function `good_enough` will
compute a different mathematical function if we substitute
`math_cos` (JavaScript's cosine function)
for `abs` in its declaration.

We have one kind of name isolation available to us so far: The parameters of a function are local to the body of the function. The square-root program illustrates another way in which we would like to control the use of names. The existing program consists of separate functions :

function sqrt(x) { return sqrt_iter(1.0, x); } function sqrt_iter(guess, x) { return good_enough(guess, x) ? guess : sqrt_iter(improve(guess, x), x); } function good_enough(guess, x) { return abs(square(guess) - x) < 0.001; } function improve(guess, x) { return average(guess, x / guess); }

The problem with this program is that the only
function
that is
important to users of `sqrt` is
`sqrt`. The other
functions
(`sqrt_iter`,
`good_enough`,
and `improve`)`good_enough`
as part of
another program to work together
with the square-root program,
because `sqrt` needs it. The
problem is especially severe in the construction of large systems by
many separate programmers. For example, in the construction of a
large library of numerical
functions,
many numerical functions are
computed as successive approximations and thus might have
functions
named
`good_enough`
and
`improve` as auxiliary
functions.
We would like to localize the
subfunctions,
hiding them inside
`sqrt` so that
`sqrt` could coexist with other
successive approximations, each having its own private
`good_enough` function.
To make this possible, we allow a
function
to have
internal declarations that are local to that
function.
For example, in the square-root problem we can write

function sqrt(x) { function good_enough(guess, x) { return abs(square(guess) - x) < 0.001; } function improve(guess, x) { return average(guess, x / guess); } function sqrt_iter(guess, x) { return good_enough(guess, x) ? guess : sqrt_iter(improve(guess, x), x); } return sqrt_iter(1.0, x); }

The body of a function—a statement enclosed in curly braces—is called a *block*.
Function declarations nested inside a block are local to that block.
This *block structure*
is basically the right solution to the simplest
name-packaging problem. But there is a better idea lurking here. In
addition to internalizing the
declarations of the auxiliary functions,
we can simplify them. Since `x`
is bound in the
declaration
of
`sqrt`, the
functions
`good_enough`,
`improve`, and
`sqrt_iter`,
which are defined internally to
`sqrt`, are in the
scope of `x`.
Thus, it is not necessary to pass
`x` explicitly to
each of these
functions.
Instead, we allow `x` to be a
free
name
in the internal
declarations,
as shown below.
Then `x`
gets its value from the argument with which the enclosing
function
`sqrt` is called. This discipline is called
*lexical
scoping*.[3]

function sqrt(x) { function good_enough(guess) { return abs(square(guess) - x) < 0.001; } function improve(guess) { return average(guess, x / guess); } function sqrt_iter(guess) { return good_enough(guess) ? guess : sqrt_iter(improve(guess)); } return sqrt_iter(1.0); }

We will use block structure extensively to help us break up large programs into tractable pieces.[4] The idea of block structure originated with the programming language Algol 60. It appears in most advanced programming languages and is an important tool for helping to organize the construction of large programs. We will see in the next section that function declarations can contain blocks other than function declarations. JavaScript's adherence to block structure is incomplete in that function declarations are local to the surrounding function declarations, not to the surrounding block. We shall therefore always place local function declarations first in the body of any function declaration.

[1] It is not even clear which of these
functions
is a
more efficient implementation. This depends upon the hardware
available. There are machines for which the

obviousimplementation is the less efficient one. Consider a machine that has extensive tables of logarithms and antilogarithms stored in a very efficient manner.

[2] The
concept of consistent renaming is actually subtle and difficult to
define formally. Famous logicians have made embarrassing errors
here.

[3] Lexical
scoping dictates that free
names in a
function
are taken to refer to
bindings made by enclosing
function declarations;
that is, they are looked up in
the environment in which the
function was declared.
We will see how
this works in detail in chapter 3 when we
study environments and the
detailed behavior of the interpreter.

[4] Embedded
declarations must come first in a function
body.
The management is not responsible
for the consequences of running programs that intertwine
declaration
and use.

1.1.8
Functions
as Black-Box Abstractions