guess
(sqrt-iter (improve guess x) x)))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (improve guess x)
(average guess (/ x guess)))
The problem with this program is that the only procedure that is important to users of
sqrt
is
sqrt
.
The other procedures (
sqrt-iter
,
good-enough?
, and
improve
) only clutter up their minds.
They may not define any other procedure 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 procedures, many numerical functions are computed as successive
approximations and thus might have procedures named
good-enough?
and
improve
as auxiliary
procedures. We would like to localize the subprocedures, hiding them inside
sqrt
so that
sqrt
could
coexist with other successive approximations, each having its own private
good-enough?
procedure. To make this possible, we allow a procedure to have internal definitions that are local to
that procedure. For example, in the square-root problem we can write
(define (sqrt x)
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (improve guess x)
(average guess (/ x guess)))
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(sqrt-iter 1.0 x))
Such nesting of definitions, 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
definitions of the auxiliary procedures, we can simplify them. Since
x
is bound in the definition of
sqrt
, the procedures
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
procedures. Instead, we allow
x
to be a free variable in the internal definitions, as shown below. Then
x
gets its value from the argument with which the enclosing procedure
sqrt
is called. This discipline
is called
lexical scoping.
27
(define (sqrt x)
(define (good-enough? guess)
(< (abs (- (square guess) x)) 0.001))
(define (improve guess)
(average guess (/ x guess)))
(define (sqrt-iter guess)
(if (good-enough? guess)
guess
(sqrt-iter (improve guess))))
(sqrt-iter 1.0))
We will use block structure extensively to help us break up large programs into tractable pieces.
28
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.
4
The characterization of numbers as ‘‘simple data’’ is a barefaced bluff. In fact, the treatment of
numbers is one of the trickiest and most confusing aspects of any programming language. Some
typical issues involved are these: Some computer systems distinguish integers, such as 2, from real
numbers, such as 2.71. Is the real number 2.00 different from the integer 2? Are the arithmetic
operations used for integers the same as the operations used for real numbers? Does 6 divided by 2
produce 3, or 3.0? How large a number can we represent? How many decimal places of accuracy can
we represent? Is the range of integers the same as the range of real numbers? Above and beyond these
questions, of course, lies a collection of issues concerning roundoff and truncation errors -- the entire
science of numerical analysis. Since our focus in this book is on large-scale program design rather than
on numerical techniques, we are going to ignore these problems. The numerical examples in this
chapter will exhibit the usual roundoff behavior that one observes when using arithmetic operations
that preserve a limited number of decimal places of accuracy in noninteger operations.
5
Throughout this book, when we wish to emphasize the distinction between the input typed by the
user and the response printed by the interpreter, we will show the latter in slanted characters.
6
Lisp systems typically provide features to aid the user in formatting expressions. Two especially
useful features are one that automatically indents to the proper pretty-print
position whenever a new
line is started and one that highlights the matching left parenthesis whenever a right parenthesis is
typed.
7
Lisp obeys the convention that every expression has a value. This convention, together with the old
reputation of Lisp as an inefficient language, is the source of the quip by Alan Perlis (paraphrasing
Oscar Wilde) that ‘‘Lisp programmers know the value of everything but the cost of nothing.’’
8
In this book, we do not show the interpreter’s response to evaluating definitions, since this is highly
implementation-dependent.
9
Chapter 3 will show that this notion of environment is crucial, both for understanding how the
interpreter works and for implementing interpreters.
10
It may seem strange that the evaluation rule says, as part of the first step, that we should evaluate
the leftmost element of a combination, since at this point that can only be an operator such as
+
or
*
representing a built-in primitive procedure such as addition or multiplication. We will see later that it
is useful to be able to work with combinations whose operators are themselves compound expressions.
11
Special syntactic forms that are simply convenient alternative surface structures for things that can
be written in more uniform ways are sometimes called
syntactic sugar, to
use a phrase coined by Peter
Landin. In comparison with users of other languages, Lisp programmers, as a rule, are less concerned
with matters of syntax. (By contrast, examine any Pascal manual and notice how much of it is devoted
to descriptions of syntax.) This disdain for syntax is due partly to the flexibility of Lisp, which makes
it easy to change surface syntax, and partly to the observation that many ‘‘convenient’’ syntactic
constructs, which make the language less uniform, end up causing more trouble than they are worth
when programs become large and complex. In the words of Alan Perlis, ‘‘Syntactic sugar causes
cancer of the semicolon.’’