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
a *bound symbol*, and we say that the function declaration
*binds* its
parameters.
The meaning of a
function declaration is unchanged if a bound symbol
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 symbols
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
symbols
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 names of its free
symbols,
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 function `good_enough`
will compute a different 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`) only clutter up their minds.
They may not
declare any other function
called
`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); }

Such nesting of
declarations,
called *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 declared 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.

[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