We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF or read online on Scribd
You are on page 1/ 159
The Little Schemer
Fou rt oh Be dition:
Daniel P. Friedman and Matthias Felleisen
Foreword by Gerald J. SussmanME Contents)
(Foreword ix)
(Preface_xi)
((. Toys) 2)
(2. Do It, Do It Again, and Again, and Agaii
((3. Cons the Magnificent) 32)
(4. Numbers Games) 58)
((5. *Oh My Gawd’: It’s Full of Stars) 80)
((6. Shadows) 96)
((7. Friends and Relations) 110)
((8. Lambda the Ultimate) 124)
((9. ... and Again, and Again, and Again, ...) 148)
((10. What Is the Value of All of This?) 174)
(Intermission 192)
(Index 194))Foreword
This foreword appeared in the second and third editions of The Little
LISPer. We reprint it here with the permission of the author.
In 1967 I took an introductory course in photography. Most of the students (including me) came
into that course hoping to learn how to be creative—to take pictures like the ones I admired
by artists such as Edward Weston. On the first day the teacher patiently explained the long
list of technical skills that he was going to teach us during the term. A key was Ansel Adams’
“Zone System” for previsualizing the print values (blackness in the final print) in a photograph
and how they derive from the light intensities in the scene. In support of this skill we had
to leam the use of exposure meters to measure light intensities and the use of exposure time
and development time to control the black level and the contrast in the image. This is in turn
supported by even lower level skills such as loading film, developing and printing, and mixing
chemicals, One must learn to ritualize the process of developing sensitive material so that one
gets consistent results over many years of work. The first laboratory session was devoted to
finding out that developer feels slippery and that fixer smells awful.
But what about creative composition? In order to be creative one must first gain control
of the medium. One can not even begin to think about organizing a great photograph without
having the skills to make it happen. In engineering, as in other creative arts, we must learn
to do analysis to support our efforts in synthesis. One cannot build a beautiful and functional
bridge without a knowledge of steel and dirt and considerable mathematical technique for using
this knowledge to compute the properties of structures. Similarly, one cannot build a beautiful
computer system without a deep understanding of how to “previsualize” the process generated
by the procedures one writes.
Some photographers choose to use black-and-white 8x10 plates while others choose 35mm
slides. Each has its advantages and disadvantages. Like photography, programming requires a
choice of medium. Lisp is the medium of choice for people who enjoy free style and flexibility.
Lisp was initially conceived as a theoretical vehicle for recursion theory and for symbolic
algebra. It has developed into a uniquely powerful and flexible family of software development
tools, providing wrap-around support for the rapid-prototyping of software systems. As with
other languages, Lisp provides the glue for using a vast library of canned parts, produced
by members of the user community. In Lisp, procedures are first-class data, to be passed as
arguments, returned as values, and stored in data structures. This flexibility is valuable, but,
most importantly, it provides mechanisms for formalizing, naming, and saving the idioms—the
common patterns of usage that are essential to engineering design. In addition, Lisp programs
caa easily manipulate the representations of Lisp programs—a feature that has encouraged the
development of a vast structure of program synthesis and analysis tools, such as cross-referencers.
The Little L1SPer is.a unique approach to developing the skills underlying creative program-
ming in Lisp. It painlessly packages, with considerable wit, much of the drill and practice that,
is necessary to learn the skills of constructing recursive processes and manipulating recursive
data-structures. For the student of Lisp programming, The Little LISPer can perform the same
service that Hanon’s finger exercises or Czerny’s piano studies perform for the student of piano.
Gerald J. Sussman
Cambridge, Massachusetts
Foreword ixPreface
To celebrate the twentieth anniversary of Scheme we revised The Little LISPer a
third time, gave it the more accurate title The Little Schemer, and wrote a sequel:
The Seasoned Schemer.
Programs accept data and produce data. Designing a program requires a thorough understand-
ing of data; a good program reflects the shape of the data it deals with. Most collections of data,
and hence most programs, are recursive. Recursion is the act of defining an object or solving a
problem in terms of itself.
The goal of this book is to teach the reader to think recursively. Our first task is to decide
which language to use to communicate this concept. There are three obvious choices: a natural
language, such as English; formal mathematics; or a programming language. Natural languages
are ambiguous, imprecise, and sometimes awkwardly verbose. These are all virtues for general
communication, but something of a drawback for communicating concisely as precise a concept
as recursion. The language of mathematies is the opposite of natural language: it can express
powerful formal ideas with only a few symbols. Unfortunately, the language of mathematics
is often cryptic and barely accessible without special training. The marriage of technology
and mathematics presents us with a third, almost ideal choice: a programming language. We
believe that programming languages are the best way to convey the concept of recursion. They
share with mathematics the ability to give a formal meaning to a set of symbols. But unlike
mathematics, programming languages can be directly experienced —you can take the programs in
this book, observe their behavior, modify them, and experience the effect of these modifications.
Perhaps the best programming language for teaching recursion is Scheme. Scheme is
inherently symbolic—the programmer does not have to think about the relationship between the
symbols of his own language and the representations in the computer. Recursion is Scheme’s nat-
ural computational mechanism; the primary programming activity is the creation of (potentially)
recursive definitions. Scheme implementations are predominantly interactive—the programmer
can immediately participate in and observe the behavior of his programs. And, perhaps most
importantly for our lessons at the end of this book, there is a direct correspondence between
the structure of Scheme programs and the data those programs manipulate.
Although Scheme can be described quite formally, understanding Scheme does not require
a particularly mathematical inclination. In fact, The Little Schemer is based on lecture notes
from a two-week “quickie” introduction to Scheme for students with no previous programming
experience and an admitted dislike for anything mathematical. Many of these students were
preparing for careersin public affairs. It is our belief that writing programs recursively in Scheme
is essentially simple pattern recognition. Since our only concern is recursive programming, our
treatment is limited to the whys and wherefores of just a few Scheme features: car, cdr, cons,
eq?, null?, zero?, add1, subl, number?, and, or, quote, lambda, define, and cond. Indeed, our
language is an idealized Scheme.
The Little Schemer and The Seasoned Schemer will not introduce you to the practical
world of programming, but a mastery of the concepts in these books provides a start toward
understanding the nature of computation.
Preface xiWhat You Need to Know to Read This Book
The reader must be comfortable reading English, recognizing numbers, and counting.
Acknowledgments
We are indebted to many people for their contributions and assistance throughout the devel-
‘opment of the second and third editions of this book. We thank Bruce Duba, Kent Dybvig,
Chris Haynes, Eugene Kohlbecker, Richard Salter, George Springer, Mitch Wand, and David S.
Wise for countless discussions that influenced our thinking while conceiving this book. Ghassan
Abbas, Charles Baker, David Boyer, Mike Dunn, Terry Falkenberg, Rob Friedman, John Gateley,
Mayer Goldberg, Iqbal Khan, Julia Lewall, Jon Mendelsohn, John Nienast, Jeffrey D. Perotti,
Ed Robertson, Anne Shpuntoff, Erich Smythe, Guy Steele, Todd Stein, and Larry Weisselberg
provided many important comments on the drafts of the book. We especially want to thank Bob
Filman for being such a thorough and uncompromising critic through several readings. Finally
we wish to acknowledge Nancy Garrett, Peg Fletcher, and Bob Filman for contributing to the
design and TpXery.
‘The fourth and latest edition greatly benefited from Dorai Sitaram’s incredibly clever Scheme
typesetting program SIXT;X. Kent Dybvig’s Chez Scheme made programming in Scheme a
most pleasant experience. We gratefully acknowledge criticisms and suggestions from Shelaswau
Bushnell, Richard Cobbe, David Combs, Peter Drake, Kent Dybvig, Rob Friedman, Steve Ganz,
Chris Haynes, Erik Hilsdale, Eugene Kohlbecker, Shriram Krishnamurthi, Julia Lawall, Suzanne
‘Menzel Collin McCurdy, John Nienart, Jon Rossie, Jonathan Sobel, George Springer, Guy Steele,
John David Stone, Vikram Subramaniam, Mitch Wand, and Melissa Wingard-Phillips.
Guidelines for the Reader
Do not rush through this book. Read carefully; valuable hints are scattered throughout the
text. Do not read the book in fewer than three sittings. Read systematically. If you do not fully
understand one chapter, you will understand the next one even less. The questions are ordered
by increasing difficulty; it will be hard to answer later ones if you cannot solve the earlier ones.
The book is a dialogue between you and us about interesting examples of Scheme programs.
If you can, try the examples while you read. Schemes are readily available. While there are
minor syntactic variations between different implementations of Scheme (primarily the spelling of
particular names and the domain of specific functions), Scheme is basically the same throughout
the world. To work with Scheme, you will need to define aton?, subi, and addi. which we
introduced in The Little Schemer:
(define atom?
(lambda (x) .
(and (not (pair? x)) (not (null? x)))))
To find out whether your Scheme has the correct definition of atom?, try (atom? (quote ()))
and make sure it returns #f. In fact, the material is also suited for modern Lisps such as
‘Common Lisp. To work with Lisp, you will also have to add the function aton?:
(defun aton? (x)
(not (listp x)))
xii PrefaceMoreover, you may need to modify the programs slightly. Typically, the material requires
only a few changes. Suggestions about how to try the programs in the book are provided in
the framenotes. Framenotes preceded by “S:” concern Scheme, those by “L:” concern Common
Lisp.
In chapter 4 we develop basic arithmetic from three operators: add1, sub, and zero?. Since
Scheme does not provide eddi and sub1, you must define them using the built-in primitives for
addition and subtraction. Therefore, to avoid a circularity, our basic arithmetic addition and
subtraction must be written using different symbols: + and —, respectively.
We do not give any formal definitions in this book. We believe that you can form your
own definitions and will thus remember them and understand them better than if we had
written each one for you. But be sure you know and understand the Laws and Commandments
thoroughly before passing them by. The key to learning Scheme is “pattern recognition.” The
Commandments point ont the patterns that you will have already seen. Early in the book,
some concepts are narrowed for simplicity; later, they are expanded and qualified. You should
also know that, while everything in the book is Scheme, Scheme itself is more general and
incorporates more than we could intelligibly cover in an introductory text. After you have
mastered this book, you can read and understand more advanced and comprehensive books on
Scheme.
We use a few notational conventions throughout the text, primarily changes in typeface
for different classes of symbols. Variables and the names of primitive operations are in italic.
Basic data, including numbers and representations of truth and falsehood, is set in sans serif.
Keywords, ie., define, lambda, cond, else, and, or, and quote, are in boldface. When you
try the programs, you may ignore the typefaces but not the related framenotes. To highlight
this role of typefaces, the programs in framenotes are set in a typewriter face. The typeface
distinctions can be safely ignored until chapter 10, where we treat programs as data.
Finally, Webster defines “punctuation” as the act of punctuating; specifically, the act,
practice, or system of using standardized marks in writing and printing to separate sentences
or sentence elements or to make the meaning clearer. We have taken this definition literally
and have abandoned some familiar uses of punctuation in order to make the meaning clearer.
Specifically, we have dropped the use of punctuation in the left-hand column whenever the item
that precedes such punctuation is a term in our programming language.
Food appears in many of our examples for two reasons. First, food is easier to visualize
than abstract symbols. (This is not a good book to read while dieting.) We hope the choice of
food will help you understand the examples and concepts we use. Second, we want to provide
you with a little distraction. We know how frustrating the subject matter can be, and a little
distraction will help you keep your sanity.
You are now ready to start. Good luck! We hope you will enjoy the challenges waiting for
you on the following pages.
Bon appétit!
Daniel P. Friedman
Matthias Felleisen
Preface xiiiThe Little SchemerIs it true that this is an atom?
atom!
1 1,8: (quote atom) or ‘atom
“Le and "S:" are described in the preface.
Yes,
because atom is a string of characters
beginning with the letter a.
Is it true that this is an atom?
turkey
Yes,
becanse turkey is a string of characters
beginning with a letter.
Is it true that this is an atom?
1492
Yes,
because 1492 is a string of digits.
Is it true that this is an atom?
u
Yes,
becanse u is a string of one character,
which is a letter.
Is it true that this is an atom?
rabcS
Yes,
because *abc$ is a string of characters
beginning with a letter or special character
other than a left “(” or right *)”
parenthesis.
Is it true that this is a list?
(atom)*
11,8: (quote (atom)? oF "(atom
Yes,
because (atom) is an atom enclosed by
parentheses
Is it true that this is a list?
(atom turkey or)
Yes,
because it is a collection of atoms enclosed
by parentheses.
ToysIs it true that this is a list?
(atom turkey) or
No,
because these are actually two
S-expressions not enclosed by parentheses.
The first one is a list containing two
atoms, and the second one is an atom.
Is it true that this is a list?
((atom turkey) or)
Yes,
because the two S-expressions are now
enclosed by parentheses.
Is it true that this is an S-expression?
“yz
‘Yes,
because all atoms are S-expressions.
Is it true that this is an S-expression?
(xyz)
Yes,
because it is a list.
Is it true that this is an S-expression?
(«y) 2)
‘Yes,
because all lists are S-expressions.
Ts it true that this is a list?
(how are you doing so far)
Yes,
because it is a collection of $-expressions
enclosed by parentheses.
How many S-expressions are in the list
(how are you doing so far)
and what are th
Six,
how, are, you, doing, so, and far.
Is it true that this is a list?
{((how) are) ((you) (doing so)) far)
Yes,
because it is a collection of S-expressions
enclosed by parentheses.
How many S-expressions are in the list
(((how) are) ((you) ( 0) far)
and what are they?
Three,
((how) are), ((you) (doing so)), and far.
Chapter 1Is it true that this is a list?
0
Yes,
because it contains zero S-expressions
enclosed by parentheses. This special
Scexpression is called the null (or empty)
list.
Isit true that this is an atom?
0
No,
because () is just a list.
Is it true that this isa list?
(0000)
Yes,
because it is a collection of S-expressions
enclosed by parentheses.
What is the car of ¢
where is the argument
(abe)
a,
because a is the first atom of this list.
What is the car of 1
where
Vis ((a bc) xyz)
(abe),
because (a b ¢) is the first S-expression of
this non-empty list.
What is the car of 1
where | is hotdog
No answer.
You cannot ask for the car of an atom.
What is the car of I
where Lis ()
No answer.
‘You cannot ask for the car of the empty
list.
Yen
The Law of Car
The primitive car is defined
only for non-empty lists.
Toys
aWhat is the car of
where
Lis (((hotdogs)) (and) (pickle) relish)
((hotdogs)),
read
“The list of the list of hotdogs.”
((hotdogs)) is the first S-expression of 1
What is (car 1)
where
Vis (((hotdogs)) (and) (pickle) relish)
((hotdogs)),
because (car 1) is another way to ask for
the car of the list L”
What is (car (car 1) (hotdogs).
where
1 is (((hotdogs)) (and))
What is the edr of 1 (bo),
where
Lis (a bc)
Note: “edr” is pronounced “could-er.”
because (b ¢) is the list / without (car 1).
What is the cdr of I
where
Lis ((ab c) xyz)
(x y 2),
What is the edr of I
where
1 is (hamburger)
0.
What is (edr 1)
where
Lis ((x) tn)
(to),
because (edr 1) is just another way to ask
for “the cdr of the list 1.”
What is (cdr @) No answer.
where You cannot ask for the cdr of an atom.
«is hotdogs
6 Chapter 1What is (cdr 1)
where 1 is ()
No answer.!
You cannot ask for the cdr of the null list.
Visa
The Law of Cdr
The primitive cdr is defined only for
non-empty lists. The cdr of any non-
empty list is always another list.
What is (car (cdr 1))
where
Vis ((b) (xy) ((c)))
(xy),
because ((x y) ((c))) is (edr ), and (x y) is
the car of (cdr 1)
What is (cdr (cdr 1))
where
Vis ((b) (x y) ((¢)))
What is (cdr (car 1))
where
Tis (a (b (0) 4)
((®)).
because ((x y) ((c))) is (edr 1), and (((€)))
is the edr of (cdr 1).
No answer,
since (car 1) is an atom, and cdr does not
take an atom as an argument; see The Law
of Car.
What does cer take as an argument?
What does cdr take as an argument?
It takes any non-empty list.
It takes any non-empty list.
What is the cons of the atom ¢ and the list J
where a is peanut
and
is (butter and jelly)
This can also be written “(cons a 1)”
Read: “cons the atom a onto the list 1”
(peanut butter and jelly),
because cons adds an atom to the front of
alist.
Toys