Full Code of norvig/paip-lisp for AI

main 9cea73837e43 cached
163 files
5.9 MB
1.6M tokens
4 symbols
1 requests
Download .txt
Showing preview only (6,234K chars total). Download the full file or copy to clipboard to get everything.
Repository: norvig/paip-lisp
Branch: main
Commit: 9cea73837e43
Files: 163
Total size: 5.9 MB

Directory structure:
gitextract_ci22_or4/

├── .gitignore
├── LICENSE
├── PAIP-alpha.epub
├── PAIP-safari.md
├── PAIP.txt
├── README.md
├── docs/
│   ├── .nojekyll
│   ├── README.md
│   ├── _coverpage.md
│   ├── _sidebar.md
│   ├── about-scan.md
│   ├── about.md
│   ├── appendix.md
│   ├── bibliography.md
│   ├── chapter1.md
│   ├── chapter10.md
│   ├── chapter11.md
│   ├── chapter12.md
│   ├── chapter13.md
│   ├── chapter14.md
│   ├── chapter15.md
│   ├── chapter16.md
│   ├── chapter17.md
│   ├── chapter18.md
│   ├── chapter19.md
│   ├── chapter2.md
│   ├── chapter20.md
│   ├── chapter21.md
│   ├── chapter22.md
│   ├── chapter23.md
│   ├── chapter24.md
│   ├── chapter25.md
│   ├── chapter3.md
│   ├── chapter4.md
│   ├── chapter5.md
│   ├── chapter6.md
│   ├── chapter7.md
│   ├── chapter8.md
│   ├── chapter9.md
│   ├── code.md
│   ├── css/
│   │   └── github.css
│   ├── frontmatter.md
│   ├── images/
│   │   ├── chapter14/
│   │   │   ├── diagram-14-02.drawio
│   │   │   ├── fig-14-01.drawio
│   │   │   ├── si1_e.tex
│   │   │   └── si2_e.tex
│   │   ├── chapter15/
│   │   │   ├── si1_e.tex
│   │   │   ├── si2_e.tex
│   │   │   ├── si3_e.tex
│   │   │   ├── si4_e.tex
│   │   │   ├── si5_e.tex
│   │   │   └── si7_e.tex
│   │   ├── chapter16/
│   │   │   ├── fig-16-02.drawio
│   │   │   └── si1_e.tex
│   │   ├── chapter17/
│   │   │   ├── fig-17-01.drawio
│   │   │   ├── fig-17-02.drawio
│   │   │   ├── fig-17-03.drawio
│   │   │   ├── fig-17-04.drawio
│   │   │   ├── fig-17-07.drawio
│   │   │   ├── fig-17-08.drawio
│   │   │   ├── fig-17-09.drawio
│   │   │   ├── fig-17-10.drawio
│   │   │   ├── fig-17-11.drawio
│   │   │   └── fig-17-12.drawio
│   │   ├── chapter18/
│   │   │   ├── diagram-18-01.drawio
│   │   │   ├── diagram-18-02.drawio
│   │   │   ├── diagram-18-03.drawio
│   │   │   ├── diagram-18-04.drawio
│   │   │   ├── diagram-18-05.drawio
│   │   │   ├── fig-18-01.drawio
│   │   │   ├── fig-18-02.drawio
│   │   │   └── fig-18-04.drawio
│   │   ├── chapter2/
│   │   │   └── fig-02-01.drawio
│   │   ├── chapter3/
│   │   │   ├── fig-03-01.drawio
│   │   │   ├── fig-03-02.drawio
│   │   │   ├── fig-03-03.drawio
│   │   │   └── fig-03-04.drawio
│   │   ├── chapter4/
│   │   │   ├── diagram-04-01.drawio
│   │   │   ├── diagram-04-02.drawio
│   │   │   ├── diagram-04-03.drawio
│   │   │   ├── diagram-04-04.drawio
│   │   │   ├── diagram-04-05.drawio
│   │   │   ├── diagram-04-06.drawio
│   │   │   └── diagram-04-09.drawio
│   │   ├── chapter6/
│   │   │   ├── diagram-06-01.drawio
│   │   │   ├── fig-06-01.drawio
│   │   │   ├── fig-06-02.drawio
│   │   │   ├── fig-06-03.drawio
│   │   │   ├── fig-06-04.drawio
│   │   │   └── fig-06-05.drawio
│   │   └── chapter9/
│   │       ├── si1_e.tex
│   │       ├── si2_e.tex
│   │       └── si3_e.tex
│   ├── index.html
│   ├── js/
│   │   └── highlight-lisp.js
│   ├── markdown-help.md
│   └── preface.md
├── lisp/
│   ├── auxfns.lisp
│   ├── clos.lisp
│   ├── cmacsyma.lisp
│   ├── compile1.lisp
│   ├── compile2.lisp
│   ├── compile3.lisp
│   ├── compopt.lisp
│   ├── edge-tab.lisp
│   ├── eliza-pm.lisp
│   ├── eliza.lisp
│   ├── eliza1.lisp
│   ├── examples.lisp
│   ├── gps-srch.lisp
│   ├── gps.lisp
│   ├── gps1.lisp
│   ├── grammar.lisp
│   ├── interp1.lisp
│   ├── interp2.lisp
│   ├── interp3.lisp
│   ├── intro.lisp
│   ├── krep.lisp
│   ├── krep1.lisp
│   ├── krep2.lisp
│   ├── lexicon.lisp
│   ├── loop.lisp
│   ├── macsyma.lisp
│   ├── macsymar.lisp
│   ├── mycin-r.lisp
│   ├── mycin.lisp
│   ├── open-pdf.lisp
│   ├── othello.lisp
│   ├── othello2.lisp
│   ├── overview.lisp
│   ├── patmatch.lisp
│   ├── prolog.lisp
│   ├── prolog1.lisp
│   ├── prologc.lisp
│   ├── prologc1.lisp
│   ├── prologc2.lisp
│   ├── prologcp.lisp
│   ├── search.lisp
│   ├── simple.lisp
│   ├── student.lisp
│   ├── syntax1.lisp
│   ├── syntax2.lisp
│   ├── syntax3.lisp
│   ├── tutor.lisp
│   ├── unifgram.lisp
│   ├── unify.lisp
│   └── waltz.lisp
├── meta/
│   ├── metadata.xml
│   ├── stylesheet.css
│   └── title.txt
├── paip.asd
└── scripts/
    ├── filter-ascii.rb
    ├── httpd-py.sh
    ├── httpd-rb.sh
    ├── make-code-blocks.rb
    ├── make-epub.sh
    ├── make-pdf-from-epub.sh
    ├── markdown-to-text.sh
    ├── one-offs/
    │   ├── add-page-anchors.rb
    │   └── linkify_page_numbers.rb
    ├── prepare-for-merge.rb
    ├── split-chapters-markdown.rb
    └── split-chapters.rb

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.DS_Store
.byebug_history

# from splitting chapters
docs/paradigmsofartificialintelligenceprogramming.md
docs/copyright.md
docs/dedication.md
docs/index.md
docs/paradigmsofartificialintelligenceprogramming.md
docs/tableofcontents.md

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2018 Peter Norvig

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: PAIP-safari.md
================================================
# Paradigms of Artificial Intelligence Programming
{:.book_title}

## Case Studies in Common Lisp
{:.book_subtitle}

First Edition

Peter Norvig
!!!(p) {:.titleauthor}

![logo](images/logo.jpg)



# Table of Contents
{:.fmtitle}

[Cover image](Cover.xhtml)

[Title page](B9780080571157500303.xhtml)

[Copyright page](B9780080571157500315.xhtml)

[Dedication](B9780080571157500327.xhtml)

[Preface](B9780080571157500261.xhtml)

[Why Lisp?
Why Common Lisp?](B9780080571157500261.xhtml#s0015)

[Outline of the Book](B9780080571157500261.xhtml#s0020)

[How to Use This Book](B9780080571157500261.xhtml#s0025)

[Supplementary Texts and Reference Books](B9780080571157500261.xhtml#s0030)

[A Note on Exercises](B9780080571157500261.xhtml#s0035)

[Acknowledgments](B9780080571157500261.xhtml#s0010)

[Part I: Introduction to Common Lisp](parti.xhtml)

[Chapter 1: Introduction to Lisp](B9780080571157500017.xhtml)

[1.1 Symbolic Computation](B9780080571157500017.xhtml#s0010)

[1.2 Variables](B9780080571157500017.xhtml#s0015)

[1.3 Special Forms](B9780080571157500017.xhtml#s0020)

[1.4 Lists](B9780080571157500017.xhtml#s0025)

[1.5 Defining New Functions](B9780080571157500017.xhtml#s0030)

[1.6 Using Functions](B9780080571157500017.xhtml#s0035)

[1.7 Higher-Order Functions](B9780080571157500017.xhtml#s0040)

[1.8 Other Data Types](B9780080571157500017.xhtml#s0045)

[1.9 Summary: The Lisp Evaluation Rule](B9780080571157500017.xhtml#s0050)

[1.10 What Makes Lisp Different?](B9780080571157500017.xhtml#s0055)

[1.11 Exercises](B9780080571157500017.xhtml#s1060)

[1.12 Answers](B9780080571157500017.xhtml#s0060)

[Chapter 2: A Simple Lisp Program](B9780080571157500029.xhtml)

[2.1 A Grammar for a Subset of English](B9780080571157500029.xhtml#s0010)

[2.2 A Straightforward Solution](B9780080571157500029.xhtml#s0015)

[2.3 A Rule-Based Solution](B9780080571157500029.xhtml#s0020)

[2.4 Two Paths to Follow](B9780080571157500029.xhtml#s0025)

[2.5 Changing the Grammar without Changing the Program](B9780080571157500029.xhtml#s0030)

[2.6 Using the Same Data for Several Programs](B9780080571157500029.xhtml#s0035)

[2.7 Exercises](B9780080571157500029.xhtml#s0040)

[2.8 Answers](B9780080571157500029.xhtml#s0045)

[Chapter 3: Overview of Lisp](B9780080571157500030.xhtml)

[3.1 A Guide to Lisp Style](B9780080571157500030.xhtml#s0010)

[3.2 Special Forms](B9780080571157500030.xhtml#s0015)

[3.3 Functions on Lists](B9780080571157500030.xhtml#s0065)

[3.4 Equality and Internal Representation](B9780080571157500030.xhtml#s0070)

[3.5 Functions on Sequences](B9780080571157500030.xhtml#s0075)

[3.6 Functions for Maintaining Tables](B9780080571157500030.xhtml#s0080)

[3.7 Functions on Trees](B9780080571157500030.xhtml#s0085)

[3.8 Functions on Numbers](B9780080571157500030.xhtml#s0090)

[3.9 Functions on Sets](B9780080571157500030.xhtml#s0095)

[3.10 Destructive Functions](B9780080571157500030.xhtml#s0100)

[3.11 Overview of Data Types](B9780080571157500030.xhtml#s0105)

[3.12 Input/Output](B9780080571157500030.xhtml#s0110)

[3.13 Debugging Tools](B9780080571157500030.xhtml#s0115)

[3.14 Antibugging Tools](B9780080571157500030.xhtml#s0120)

[3.15 Evaluation](B9780080571157500030.xhtml#s0135)

[3.16 Closures](B9780080571157500030.xhtml#s0140)

[3.17 Special Variables](B9780080571157500030.xhtml#s0145)

[3.18 Multiple Values](B9780080571157500030.xhtml#s0150)

[3.19 More about Parameters](B9780080571157500030.xhtml#s0155)

[3.20 The Rest of Lisp](B9780080571157500030.xhtml#s0160)

[3.21 Exercises](B9780080571157500030.xhtml#s0165)

[3.22 Answers](B9780080571157500030.xhtml#s0170)

[Part II: Early AI Programs](partii.xhtml)

[Chapter 4: GPS: The General Problem Solver](B9780080571157500042.xhtml)

[4.1 Stage 1: Description](B9780080571157500042.xhtml#s0010)

[4.2 Stage 2: Specification](B9780080571157500042.xhtml#s0015)

[4.3 Stage 3: Implementation](B9780080571157500042.xhtml#s0020)

[4.4 Stage 4: Test](B9780080571157500042.xhtml#s0025)

[4.5 Stage 5: Analysis, or "We Lied about the G"](B9780080571157500042.xhtml#s0030)

[4.6 The Running Around the Block Problem](B9780080571157500042.xhtml#s0035)

[4.7 The Clobbered Sibling Goal Problem](B9780080571157500042.xhtml#s0040)

[4.8 The Leaping before You Look Problem](B9780080571157500042.xhtml#s0045)

[4.9 The Recursive Subgoal Problem](B9780080571157500042.xhtml#s0050)

[4.10 The Lack of Intermediate Information Problem](B9780080571157500042.xhtml#s0055)

[4.11 GPS Version 2: A More General Problem Solver](B9780080571157500042.xhtml#s0060)

[4.12 The New Domain Problem: Monkey and Bananas](B9780080571157500042.xhtml#s0065)

[4.13 The Maze Searching Domain](B9780080571157500042.xhtml#s0070)

[4.14 The Blocks World Domain](B9780080571157500042.xhtml#s0075)

[4.15 Stage 5 Repeated: Analysis of Version 2](B9780080571157500042.xhtml#s0090)

[4.16 The Not Looking after You Don't Leap Problem](B9780080571157500042.xhtml#s0095)

[4.17 The Lack of Descriptive Power Problem](B9780080571157500042.xhtml#s0100)

[4.18 The Perfect Information Problem](B9780080571157500042.xhtml#s0105)

[4.19 The Interacting Goals Problem](B9780080571157500042.xhtml#s0110)

[4.20 The End of GPS](B9780080571157500042.xhtml#s0115)

[4.21 History and References](B9780080571157500042.xhtml#s0120)

[4.22 Exercises](B9780080571157500042.xhtml#s0125)

[4.23 Answers](B9780080571157500042.xhtml#s0130)

[Chapter 5: Eliza: Dialog with a Machine](B9780080571157500054.xhtml)

[5.1 Describing and Specifying ELIZA !!!(span) {:.smallcaps}](B9780080571157500054.xhtml#s0010)

[5.2 Pattern Matching](B9780080571157500054.xhtml#s0015)

[5.3 Segment Pattern Matching](B9780080571157500054.xhtml#s0020)

[5.4 The ELIZA !!!(span) {:.smallcaps} Program: A Rule-Based Translator](B9780080571157500054.xhtml#s0025)

[5.5 History and References](B9780080571157500054.xhtml#s0030)

[5.6 Exercises](B9780080571157500054.xhtml#s0035)

[5.7 Answers](B9780080571157500054.xhtml#s0040)

[Chapter 6: Building Software Tools](B9780080571157500066.xhtml)

[6.1 An Interactive Interpreter Tool](B9780080571157500066.xhtml#s0010)

[6.2 A Pattern-Matching Tool](B9780080571157500066.xhtml#s0015)

[6.3 A Rule-Based Translator Tool](B9780080571157500066.xhtml#s0020)

[6.4 A Set of Searching Tools](B9780080571157500066.xhtml#s0025)

[6.5 GPS as Search](B9780080571157500066.xhtml#s0060)

[6.6 History and References](B9780080571157500066.xhtml#s0065)

[6.7 Exercises](B9780080571157500066.xhtml#s0070)

[6.8 Answers](B9780080571157500066.xhtml#s0075)

[Chapter 7: STUDENT !!!(span) {:.smallcaps} : Solving Algebra Word Problems](B9780080571157500078.xhtml)

[7.1 Translating English into Equations](B9780080571157500078.xhtml#s0010)

[7.2 Solving Algebraic Equations](B9780080571157500078.xhtml#s0015)

[7.3 Examples](B9780080571157500078.xhtml#s0020)

[7.4 History and References](B9780080571157500078.xhtml#s0025)

[7.5 Exercises](B9780080571157500078.xhtml#s0030)

[7.6 Answers](B9780080571157500078.xhtml#s0035)

[Chapter 8: Symbolic Mathematics: A Simplification Program](B978008057115750008X.xhtml)

[8.1 Converting Infix to Prefix Notation](B978008057115750008X.xhtml#s0010)

[8.2 Simplification Rules](B978008057115750008X.xhtml#s0015)

[8.3 Associativity and Commutativity](B978008057115750008X.xhtml#s0020)

[8.4 Logs, Trig, and Differentiation](B978008057115750008X.xhtml#s0025)

[8.5 Limits of Rule-Based Approaches](B978008057115750008X.xhtml#s0030)

[8.6 Integration](B978008057115750008X.xhtml#s0035)

[8.7 History and References](B978008057115750008X.xhtml#s0040)

[8.8 Exercises](B978008057115750008X.xhtml#s0045)

[Part III: Tools and Techniques](partiii.xhtml)

[Chapter 9: Efficiency Issues](B9780080571157500091.xhtml)

[9.1 Caching Results of Previous Computations: Memoization](B9780080571157500091.xhtml#s0010)

[9.2 Compiling One Language into Another](B9780080571157500091.xhtml#s0015)

[9.3 Delaying Computation](B9780080571157500091.xhtml#s0020)

[9.4 Indexing Data](B9780080571157500091.xhtml#s0025)

[9.5 Instrumentation: Deciding What to Optimize](B9780080571157500091.xhtml#s0030)

[9.6 A Case Study in Efficiency: The SIMPLIFY Program](B9780080571157500091.xhtml#s0035)

[9.7 History and References](B9780080571157500091.xhtml#s0070)

[9.8 Exercises](B9780080571157500091.xhtml#s0075)

[9.9 Answers](B9780080571157500091.xhtml#s0080)

[Chapter 10: Low-Level Efficiency Issues](B9780080571157500108.xhtml)

[10.1 Use Declarations](B9780080571157500108.xhtml#s0010)

[10.2 Avoid Generic Functions](B9780080571157500108.xhtml#s0015)

[10.3 Avoid Complex Argument Lists](B9780080571157500108.xhtml#s0020)

[10.4 Avoid Unnecessary Consing](B9780080571157500108.xhtml#s0025)

[10.5 Use the Right Data Structures](B9780080571157500108.xhtml#s0030)

[10.6 Exercises](B9780080571157500108.xhtml#s0035)

[10.7 Answers](B9780080571157500108.xhtml#s0040)

[Chapter 11: Logic Programming](B978008057115750011X.xhtml)

[11.1 Idea 1: A Uniform Data Base](B978008057115750011X.xhtml#s0010)

[11.2 Idea 2: Unification of Logic Variables](B978008057115750011X.xhtml#s0015)

[11.3 Idea 3: Automatic Backtracking](B978008057115750011X.xhtml#s0025)

[11.4 The Zebra Puzzle](B978008057115750011X.xhtml#s0040)

[11.5 The Synergy of Backtracking and Unification](B978008057115750011X.xhtml#s0045)

[11.6 Destructive Unification](B978008057115750011X.xhtml#s0050)

[11.7 Prolog in Prolog](B978008057115750011X.xhtml#s0055)

[11.8 Prolog Compared to Lisp](B978008057115750011X.xhtml#s0060)

[11.9 History and References](B978008057115750011X.xhtml#s0065)

[11.10 Exercises](B978008057115750011X.xhtml#s0070)

[11.11 Answers](B978008057115750011X.xhtml#s0075)

[Chapter 12: Compiling Logic Programs](B9780080571157500121.xhtml)

[12.1 A Prolog Compiler](B9780080571157500121.xhtml#s0010)

[12.2 Fixing the Errors in the Compiler](B9780080571157500121.xhtml#s0015)

[12.3 Improving the Compiler](B9780080571157500121.xhtml#s0020)

[12.4 Improving the Compilation of Unification](B9780080571157500121.xhtml#s0025)

[12.5 Further Improvements to Unification](B9780080571157500121.xhtml#s0030)

[12.6 The User Interface to the Compiler](B9780080571157500121.xhtml#s0035)

[12.7 Benchmarking the Compiler](B9780080571157500121.xhtml#s0040)

[12.8 Adding More Primitives](B9780080571157500121.xhtml#s0045)

[12.9 The Cut](B9780080571157500121.xhtml#s0050)

[12.10 "Real" Prolog](B9780080571157500121.xhtml#s0055)

[12.11 History and References](B9780080571157500121.xhtml#s0060)

[12.12 Exercises](B9780080571157500121.xhtml#s0065)

[12.13 Answers](B9780080571157500121.xhtml#s0070)

[Chapter 13: Object-Oriented Programming](B9780080571157500133.xhtml)

[13.1 Object-Oriented Programming](B9780080571157500133.xhtml#s0010)

[13.2 Objects](B9780080571157500133.xhtml#s0015)

[13.3 Generic Functions](B9780080571157500133.xhtml#s0020)

[13.4 Classes](B9780080571157500133.xhtml#s0025)

[13.5 Delegation](B9780080571157500133.xhtml#s0030)

[13.6 Inheritance](B9780080571157500133.xhtml#s0035)

[13.7 CLOS: The Common Lisp Object System](B9780080571157500133.xhtml#s0040)

[13.8 A CLOS Example: Searching Tools](B9780080571157500133.xhtml#s0045)

[13.9 Is CLOS Object-Oriented?](B9780080571157500133.xhtml#s0060)

[13.10 Advantages of Object-Oriented Programming](B9780080571157500133.xhtml#s0065)

[13.11 History and References](B9780080571157500133.xhtml#s0070)

[13.12 Exercises](B9780080571157500133.xhtml#s0075)

[Chapter 14: Knowledge Representation and Reasoning](B9780080571157500145.xhtml)

[14.1 A Taxonomy of Representation Languages](B9780080571157500145.xhtml#s0010)

[14.2 Predicate Calculus and its Problems](B9780080571157500145.xhtml#s0015)

[14.3 A Logical Language: Prolog](B9780080571157500145.xhtml#s0020)

[14.4 Problems with Prolog's Expressiveness](B9780080571157500145.xhtml#s0025)

[14.5 Problems with Predicate Calculus's Expressiveness](B9780080571157500145.xhtml#s0030)

[14.6 Problems with Completeness](B9780080571157500145.xhtml#s0035)

[14.7 Problems with Efficiency: Indexing](B9780080571157500145.xhtml#s0040)

[14.8 A Solution to the Indexing Problem](B9780080571157500145.xhtml#s0045)

[14.9 A Solution to the Completeness Problem](B9780080571157500145.xhtml#s0050)

[14.10 Solutions to the Expressiveness Problems](B9780080571157500145.xhtml#s0055)

[14.11 History and References](B9780080571157500145.xhtml#s0085)

[14.12 Exercises](B9780080571157500145.xhtml#s0090)

[14.13 Answers](B9780080571157500145.xhtml#s0095)

[Part IV: Advanced AI Programs](partiv.xhtml)

[Chapter 15: Symbolic Mathematics with Canonical Forms](B9780080571157500157.xhtml)

[15.1 A Canonical Form for Polynomials](B9780080571157500157.xhtml#s0010)

[15.2 Differentiating Polynomials](B9780080571157500157.xhtml#s0015)

[15.3 Converting between Infix and Prefix](B9780080571157500157.xhtml#s0020)

[15.4 Benchmarking the Polynomial Simplifier](B9780080571157500157.xhtml#s0025)

[15.5 A Canonical Form for Rational Expressions](B9780080571157500157.xhtml#s0030)

[15.6 Extending Rational Expressions](B9780080571157500157.xhtml#s0035)

[15.7 History and References](B9780080571157500157.xhtml#s0040)

[15.8 Exercises](B9780080571157500157.xhtml#s0045)

[15.9 Answers](B9780080571157500157.xhtml#s0050)

[Chapter 16: Expert Systems](B9780080571157500169.xhtml)

[16.1 Dealing with Uncertainty](B9780080571157500169.xhtml#s0010)

[16.2 Caching Derived Facts](B9780080571157500169.xhtml#s0015)

[16.3 Asking Questions](B9780080571157500169.xhtml#s0020)

[16.4 Contexts Instead of Variables](B9780080571157500169.xhtml#s0025)

[16.5 Backward-Chaining Revisited](B9780080571157500169.xhtml#s0030)

[16.6 Interacting with the Expert](B9780080571157500169.xhtml#s0035)

[16.7 Interacting with the Client](B9780080571157500169.xhtml#s0040)

[16.8 MYCIN !!!(span) {:.smallcaps} , A Medical Expert System](B9780080571157500169.xhtml#s0045)

[16.9 Alternatives to Certainty Factors](B9780080571157500169.xhtml#s0050)

[16.10 History and References](B9780080571157500169.xhtml#s0055)

[16.11 Exercises](B9780080571157500169.xhtml#s0060)

[16.12 Answers](B9780080571157500169.xhtml#s0065)

[Chapter 17: Line-Diagram Labeling by Constraint Satisfaction](B9780080571157500170.xhtml)

[17.1 The Line-Labeling Problem](B9780080571157500170.xhtml#s0010)

[17.2 Combining Constraints and Searching](B9780080571157500170.xhtml#s0015)

[17.3 Labeling Diagrams](B9780080571157500170.xhtml#s0020)

[17.4 Checking Diagrams for Errors](B9780080571157500170.xhtml#s0025)

[17.5 History and References](B9780080571157500170.xhtml#s0030)

[17.6 Exercises](B9780080571157500170.xhtml#s0035)

[Chapter 18: Search and the Game of Othello](B9780080571157500182.xhtml)

[18.1 The Rules of the Game](B9780080571157500182.xhtml#s0010)

[18.2 Representation Choices](B9780080571157500182.xhtml#s0015)

[18.3 Evaluating Positions](B9780080571157500182.xhtml#s0020)

[18.4 Searching Ahead: Minimax](B9780080571157500182.xhtml#s0025)

[18.5 Smarter Searching: Alpha-Beta Search](B9780080571157500182.xhtml#s0030)

[18.6 An Analysis of Some Games](B9780080571157500182.xhtml#s0035)

[18.7 The Tournament Version of Othello](B9780080571157500182.xhtml#s0040)

[18.8 Playing a Series of Games](B9780080571157500182.xhtml#s0045)

[18.9 More Efficient Searching](B9780080571157500182.xhtml#s0050)

[18.10 It Pays to Precycle](B9780080571157500182.xhtml#s0055)

[18.11 Killer Moves](B9780080571157500182.xhtml#s0060)

[18.12 Championship Programs: Iago and Bill](B9780080571157500182.xhtml#s0065)

[18.13 Other Techniques](B9780080571157500182.xhtml#s0085)

[18.14 History and References](B9780080571157500182.xhtml#s0135)

[18.15 Exercises](B9780080571157500182.xhtml#s0140)

[18.16 Answers](B9780080571157500182.xhtml#s0145)

[Chapter 19: Introduction to Natural Language](B9780080571157500194.xhtml)

[19.1 Parsing with a Phrase-Structure Grammar](B9780080571157500194.xhtml#s0010)

[19.2 Extending the Grammar and Recognizing Ambiguity](B9780080571157500194.xhtml#s0015)

[19.3 More Efficient Parsing](B9780080571157500194.xhtml#s0020)

[19.4 The Unknown-Word Problem](B9780080571157500194.xhtml#s0025)

[19.5 Parsing into a Semantic Representation](B9780080571157500194.xhtml#s0030)

[19.6 Parsing with Preferences](B9780080571157500194.xhtml#s0035)

[19.7 The Problem with Context-Free Phrase-Structure Rules](B9780080571157500194.xhtml#s0040)

[19.8 History and References](B9780080571157500194.xhtml#s0045)

[19.9 Exercises](B9780080571157500194.xhtml#s0050)

[19.10 Answers](B9780080571157500194.xhtml#s0055)

[Chapter 20: Unification Grammars](B9780080571157500200.xhtml)

[20.1 Parsing as Deduction](B9780080571157500200.xhtml#s0010)

[20.2 Definite Clause Grammars](B9780080571157500200.xhtml#s0015)

[20.3 A Simple Grammar in DCG Format](B9780080571157500200.xhtml#s0020)

[20.4 A DCG Grammar with Quantifiers](B9780080571157500200.xhtml#s0025)

[20.5 Preserving Quantifier Scope Ambiguity](B9780080571157500200.xhtml#s0030)

[20.6 Long-Distance Dependencies](B9780080571157500200.xhtml#s0035)

[20.7 Augmenting DCG Rules](B9780080571157500200.xhtml#s0040)

[20.8 History and References](B9780080571157500200.xhtml#s0045)

[20.9 Exercises](B9780080571157500200.xhtml#s0050)

[20.10 Answers](B9780080571157500200.xhtml#s0055)

[Chapter 21: A Grammar of English](B9780080571157500212.xhtml)

[21.1 Noun Phrases](B9780080571157500212.xhtml#s0010)

[21.2 Modifiers](B9780080571157500212.xhtml#s0015)

[21.3 Noun Modifiers](B9780080571157500212.xhtml#s0020)

[21.4 Determiners](B9780080571157500212.xhtml#s0025)

[21.5 Verb Phrases](B9780080571157500212.xhtml#s0030)

[21.6 Adverbs](B9780080571157500212.xhtml#s0035)

[21.7 Clauses](B9780080571157500212.xhtml#s0040)

[21.8 Sentences](B9780080571157500212.xhtml#s0045)

[21.9 XPs](B9780080571157500212.xhtml#s0050)

[21.10 Word Categories](B9780080571157500212.xhtml#s0055)

[21.11 The Lexicon](B9780080571157500212.xhtml#s0060)

[21.12 Supporting the Lexicon](B9780080571157500212.xhtml#s0115)

[21.13 Other Primitives](B9780080571157500212.xhtml#s0120)

[21.14 Examples](B9780080571157500212.xhtml#s0125)

[21.15 History and References](B9780080571157500212.xhtml#s0130)

[21.16 Exercises](B9780080571157500212.xhtml#s0135)

[Part V: The Rest of Lisp](partv.xhtml)

[Chapter 22: Scheme: An Uncommon Lisp](B9780080571157500224.xhtml)

[22.1 A Scheme Interpreter](B9780080571157500224.xhtml#s0010)

[22.2 Syntactic Extension with Macros](B9780080571157500224.xhtml#s0015)

[22.3 A Properly Tail-Recursive Interpreter](B9780080571157500224.xhtml#s0020)

[22.4 Throw, Catch, and Call/cc](B9780080571157500224.xhtml#s0025)

[22.5 An Interpreter Supporting Call/cc](B9780080571157500224.xhtml#s0030)

[22.6 History and References](B9780080571157500224.xhtml#s0035)

[22.7 Exercises](B9780080571157500224.xhtml#s0040)

[22.8 Answers](B9780080571157500224.xhtml#s0045)

[Chapter 23: Compiling Lisp](B9780080571157500236.xhtml)

[23.1 A Properly Tail-Recursive Lisp Compiler](B9780080571157500236.xhtml#s0010)

[23.2 Introducing Call/cc](B9780080571157500236.xhtml#s0015)

[23.3 The Abstract Machine](B9780080571157500236.xhtml#s0020)

[23.4 A Peephole Optimizer](B9780080571157500236.xhtml#s0025)

[23.5 Languages with Different Lexical Conventions](B9780080571157500236.xhtml#s0030)

[23.6 History and References](B9780080571157500236.xhtml#s0035)

[23.7 Exercises](B9780080571157500236.xhtml#s0040)

[23.8 Answers](B9780080571157500236.xhtml#s0045)

[Chapter 24: ANSI Common Lisp](B9780080571157500248.xhtml)

[24.1 Packages](B9780080571157500248.xhtml#s0010)

[24.2 Conditions and Error Handling](B9780080571157500248.xhtml#s0020)

[24.3 Pretty Printing](B9780080571157500248.xhtml#s0035)

[24.4 Series](B9780080571157500248.xhtml#s0040)

[24.5 The Loop Macro](B9780080571157500248.xhtml#s0045)

[24.6 Sequence Functions](B9780080571157500248.xhtml#s0090)

[24.7 Exercises](B9780080571157500248.xhtml#s0115)

[24.8 Answers](B9780080571157500248.xhtml#s0120)

[Chapter 25: Troubleshooting](B978008057115750025X.xhtml)

[25.1 Nothing Happens](B978008057115750025X.xhtml#s0010)

[25.2 Change to Variable Has No Effect](B978008057115750025X.xhtml#s0015)

[25.3 Change to Function Has No Effect](B978008057115750025X.xhtml#s0020)

[25.4 Values Change "by Themselves"](B978008057115750025X.xhtml#s0025)

[25.5 Built-In Functions Don't Find Elements](B978008057115750025X.xhtml#s0030)

[25.6 Multiple Values Are Lost](B978008057115750025X.xhtml#s0035)

[25.7 Declarations Are Ignored](B978008057115750025X.xhtml#s0040)

[25.8 My Lisp Does the Wrong Thing](B978008057115750025X.xhtml#s0045)

[25.9 How to Find the Function You Want](B978008057115750025X.xhtml#s0050)

[25.10 Syntax of LOOP](B978008057115750025X.xhtml#s0055)

[25.11 Syntax of COND](B978008057115750025X.xhtml#s0060)

[25.12 Syntax of CASE](B978008057115750025X.xhtml#s0065)

[25.13 Syntax of LET and LET*](B978008057115750025X.xhtml#s0070)

[25.14 Problems with Macros](B978008057115750025X.xhtml#s0075)

[25.15 A Style Guide to Lisp](B978008057115750025X.xhtml#s0080)

[25.16 Dealing with Files, Packages, and Systems](B978008057115750025X.xhtml#s0110)

[25.17 Portability Problems](B978008057115750025X.xhtml#s0115)

[25.18 Exercises](B978008057115750025X.xhtml#s0120)

[25.19 Answers](B978008057115750025X.xhtml#s0125)

[Appendix: Obtaining the Code in this Book](B9780080571157500273.xhtml)

[FTP: The File Transfer Protocol](B9780080571157500273.xhtml#s0010)

[Available Software](B9780080571157500273.xhtml#s0015)

[Bibliography](B9780080571157500285.xhtml)

[Index](B9780080571157500297_1.xhtml)



# Copyright
{:#cop0005}
{:.fmtitle}

Sponsoring Editor *Michael B.
Morgan*
!!!(p) {:.copyright-top}

Production Manager *Yonie Overton*
!!!(p) {:.copyright}

Cover Designer *Sandra Popovich*
!!!(p) {:.copyright}

Text Design/Composition *SuperScript Typography*
!!!(p) {:.copyright}

Copyeditor *Barbara Beidler Kendrick*
!!!(p) {:.copyright}

Proofreaders *Lynn Meinhardt, Sharilyn Hovind, Gary Morris*
!!!(p) {:.copyright}

Printer *Malloy Lithographing*
!!!(p) {:.copyright}

Morgan Kaufmann Publishers, Inc.
!!!(p) {:.copyright-top}

*Editorial and Sales Office:*
!!!(p) {:.copyright}

340 Pine Street, Sixth Floor
!!!(p) {:.copyright}

San Francisco, CA 94104-3205
!!!(p) {:.copyright}

USA
!!!(p) {:.copyright}

*Telephone* 415/392-2665
!!!(p) {:.copyright}

*Facsimile* 415/982-2665
!!!(p) {:.copyright}

*Internet*[mkp@mkp.com](mailto:mkp@mkp.com)
!!!(p) {:.copyright}

*Web site*[http://mkp.com](http://mkp.com)
!!!(p) {:.copyright}

@ 1992 Morgan Kaufmann Publishers, Inc.
!!!(p) {:.copyright-top}

All rights reserved
!!!(p) {:.copyright}

Printed in the United States of America
!!!(p) {:.copyright}

03 02 01 8 7 6
!!!(p) {:.copyright-top}

No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means-electronic, photocopying, recording, or otherwise-without the prior written permission of the publisher.
!!!(p) {:.copyright-top}

Library of Congress Cataloging-in-Publication Data
!!!(p) {:.copyright-top}

Norvig, Peter.
!!!(p) {:.copyright-top}

Paradigms of artificial intelligence programming: case studies in common Lisp / Peter Norvig.
!!!(p) {:.copyright}

p. cm.
!!!(p) {:.copyright}

Includes bibliographical references and index.
!!!(p) {:.copyright}

ISBN 1-55860-191-0:
!!!(p) {:.copyright}

1.
Electronic digital computers-Programming.
2.
COMMON LISP (Computer program language) 3.
Artificial intelligence. I.
Title.
!!!(p) {:.copyright}

QA76.6.N687 1991
!!!(p) {:.copyright}

006.3-dc20    91-39187
!!!(p) {:.copyright}

CIP
!!!(p) {:.copyright}



# Dedication
{:#ded0005}
{:.fmtitle}

*To my family*...
!!!(p) {:.dedication}



# Preface
{:#pre0005}
{:.fmtitle}

> **paradigm***n***1** an example or pattern; *esp* an outstandingly clear or typical example.

> -*Longman's Dictionary of the English Language*, 1984

This book is concerned with three related topics: the field of artificial intelligence, or AI; the skill of computer programming; and the programming language Common Lisp.
Careful readers of this book can expect to come away with an appreciation of the major questions and techniques of AI, an understanding of some important AI programs, and an ability to read, modify, and create programs using Common Lisp.
The examples in this book are designed to be clear examples of good programming style-paradigms of programming.
They are also paradigms of AI research-historically significant programs that use widely applicable techniques to solve important problems.

Just as a liberal arts education includes a course in "the great books" of a culture, so this book is, at one level, a course in "the great programs" that define the AI culture.[1](#fn0010)

At another level, this book is a highly technical compendium of the knowledge you will need to progress from being an intermediate Lisp programmer to being an expert.
Parts I and II are designed to help the novice get up to speed, but the complete beginner may have a hard time even with this material.
Fortunately, there are at least five good texts available for the beginner; see page xiii for my recommendations.

All too often, the teaching of computer programming consists of explaining the syntax of the chosen language, showing the student a 10-line program, and then asking the student to write programs.
In this book, we take the approach that the best way to learn to write is to read (and conversely, a good way to improve reading skills is to write).
After the briefest of introductions to Lisp, we start right off with complex programs and ask the reader to understand and make small modifications to these programs.

The premise of this book is that you can only write something useful and interesting when you both understand what makes good writing and have something interesting to say.
This holds for writing programs as well as for writing prose.
As Kernighan and Plauger put it on the cover of *Software Tools in Pascal:*

> Good programming is not learned from generalities, but by seeing how significant programs can be made clean, easy to read, easy to maintain and modify, human-engineered, efficient, and reliable, by the application of common sense and good programming practices.
Careful study and imitation of good programs leads to better writing.

The proud craftsman is often tempted to display only the finished work, without any indication of the false starts and mistakes that are an unfortunate but unavoidable part of the creative process.
Unfortunately, this reluctance to unveil the process is a barrier to learning; a student of mathematics who sees a beautiful 10-line proof in a textbook can marvel at its conciseness but does not learn how to construct such a proof.
This book attempts to show the complete programming process, "warts and all." Each chapter starts with a simple version of a program, one that works on some examples but fails on others.
Each chapter shows how these failures can be analyzed to build increasingly sophisticated versions of the basic program.
Thus, the reader can not only appreciate the final result but also see how to learn from mistakes and refine an initially incomplete design.
Furthermore, the reader who finds a particular chapter is becoming too difficult can skip to the next chapter, having gained some appreciation of the problem area, and without being overwhelmed by the details.

This book presents a body of knowledge loosely known as "AI programming techniques," but it must be recognized that there are no clear-cut boundaries on this body of knowledge.
To be sure, no one can be a good AI programmer without first being a good programmer.
Thus, this book presents topics (especially in parts III and V) that are not AI per se, but are essential background for any AI practitioner.

## Why Lisp? Why Common Lisp?
{:#s0015}
{:.h1hd}

Lisp is one of the oldest programming languages still in widespread use today.
There have been many versions of Lisp, each sharing basic features but differing in detail.
In this book we use the version called Common Lisp, which is the most widely accepted standard.
Lisp has been chosen for three reasons.
!!!(p) {:.para_fl}

First, Lisp is the most popular language for AI programming, particularly in the United States.
If you're going to learn a language, it might as well be one with a growing literature, rather than a dead tongue.

Second, Lisp makes it easy to capture relevant generalizations in defining new objects.
In particular, Lisp makes it easy to define new languages especially targeted to the problem at hand.
This is especially handy in AI applications, which often manipulate complex information that is most easily represented in some novel form.
Lisp is one of the few languages that allows full flexibility in defining and manipulating programs as well as data.
All programming languages, by definition, provide a means of defining programs, but many other languages limit the ways in which a program can be used, or limit the range of programs that can be defined, or require the programmer to explicitly state irrelevant details.

Third, Lisp makes it very easy to develop a working program fast.
Lisp programs are concise and are uncluttered by low-level detail.
Common Lisp offers an unusually large number of useful predefined objects, including over 700 functions.
The programming environment (such as debugging tools, incremental compilers, integrated editors, and interfaces to window systems) that surround Lisp systems are usually very good.
And the dynamic, interactive nature of Lisp makes it easy to experiment and change a program while it is being developed.

It must be mentioned that in Europe and Japan, Prolog has been as popular as Lisp for AI work.
Prolog shares most of Lisp's advantages in terms of flexibility and conciseness.
Recently, Lisp has gained popularity worldwide, and Prolog is becoming more well known in the United States.
As a result, the average AI worker today is likely to be bilingual.
This book presents the key ideas behind Prolog in [chapters 11](B978008057115750011X.xhtml) and [12](B9780080571157500121.xhtml), and uses these ideas in subsequent chapters, particularly [20](B9780080571157500200.xhtml) and [21](B9780080571157500212.xhtml).

The dialect of Lisp known as Scheme is also gaining in popularity, but primarily for teaching and experimenting with programming language design and techniques, and not so much for writing large AI programs.
Scheme is presented in [chapters 22](B9780080571157500224.xhtml) and [23](B9780080571157500236.xhtml).
Other dialects of Lisp such as Franz Lisp, MacLisp, InterLisp, ZetaLisp, and Standard Lisp are now considered obsolete.
The only new dialect of Lisp to be proposed recently is EuLisp, the European Lisp.
A few dialects of Lisp live on as embedded extension languages.
For example, the Gnu Emacs text editor uses elisp, and the AutoCad computer-aided design package uses AutoLisp, a derivative of Xlisp.
In the future, it is likely that Scheme will become a popular extension language, since it is small but powerful and has an officially sanctioned standard definition.

There is a myth that Lisp (and Prolog) are "special-purpose" languages, while languages like Pascal and C are "general purpose." Actually, just the reverse is true.
Pascal and C are special-purpose languages for manipulating the registers and memory of a von Neumann-style computer.
The majority of their syntax is devoted to arithmetic and Boolean expressions, and while they provide some facilities for forming data structures, they have poor mechanisms for procedural abstraction or control abstraction.
In addition, they are designed for the state-oriented style of programming: computing a result by changing the value of variables through assignment statements.

Lisp, on the other hand, has no special syntax for arithmetic.
Addition and multiplication are no more or less basic than list operations like appending, or string operations like converting to upper case.
But Lisp provides all you will need for programming in general: defining data structures, functions, and the means for combining them.

The assignment-dominated, state-oriented style of programming is possible in Lisp, but in addition object-oriented, rule-based, and functional styles are all supported within Lisp.
This flexibility derives from two key features of Lisp: First, Lisp has a powerful *macro* facility, which can be used to extend the basic language.
When new styles of programming were invented, other languages died out; Lisp simply incorporated the new styles by defining some new macros.
The macro facility is possible because Lisp programs are composed of a simple data structure: the list.
In the early days, when Lisp was interpreted, most manipulation of programs was done through this data structure.
Nowadays, Lisp is more often compiled than interpreted, and programmers rely more on Lisp's second great flexible feature: the *function*.
Of course, other languages have functions, but Lisp is rare in allowing the creation of new functions while a program is running.

Lisp's flexibility allows it to adapt as programming styles change, but more importantly, Lisp can adapt to your particular programming problem.
In other languages you fit your problem to the language; with Lisp you extend the language to fit your problem.

Because of its flexibility, Lisp has been succesful as a high-level language user for rapid prototyping in areas such as AI, graphics, and interfaces.
Lisp has also been the dominant language for exploratory programming, where the problems are so complex that no clear solution is available at the start of the project.
Much of AI falls under this heading.

The size of Common Lisp can be either an advantage or a disadvantage, depending on your outlook.
In [David Touretzky's (1989)](B9780080571157500285.xhtml#bb1240) fine book for beginning programmers, the emphasis is on simplicity.
He chooses to write some programs slightly less concisely, rather than introduce an esoteric new feature (he cites `pushnew` as an example).
That approach is entirely appropriate for beginners, but this book goes well past the level of beginner.
This means exposing the reader to new features of the language whenever they are appropriate.
Most of the time, new features are described as they are introduced, but sometimes explaining the details of a low-level function would detract from the explanation of the workings of a program.
In accepting the privilege of being treated as an "adult," the reader also accepts a responsibility-to look up unfamiliar terms in an appropriate reference source.

## Outline of the Book
{:#s0020}
{:.h1hd}

This book is organized into five parts.
!!!(p) {:.para_fl}

**[Part I](parti.xhtml)** introduces the Common Lisp programming language.

[Chapter 1](B9780080571157500017.xhtml) gives a quick introduction by way of small examples that demonstrate the novel features of Lisp.
It can be safely skipped or skimmed by the experienced programmer.

[Chapter 2](B9780080571157500029.xhtml) is a more extended example showing how the Lisp primitives can be put together to form a program.
It should be studied carefully by the novice, and even the experienced programmer will want to look through it to get a feel for my programming style.

[Chapter 3](B9780080571157500030.xhtml) provides an overview of the Lisp primitives.
It can be skimmed on first reading and used as a reference whenever an unfamiliar function is mentioned in the text.

[Part I](parti.xhtml) has been kept intentionally brief, so that there is more room for presenting actual AI programs.
Unfortunately, that means that another text or reference book (or online help) may be needed to clarify some of the more esoteric features of the language.
My recommendations for texts are on page xiii.

The reader may also want to refer to [chapter 25](B978008057115750025X.xhtml), which offers some debugging and troubleshooting hints.

**[Part II](partii.xhtml)** covers four early AI programs that all use rule-based pattern-matching techniques.
By starting with relatively simple versions of the programs and then improving them and moving on to more complex programs, the reader is able to gradually acquire increasingly advanced programming skills.

[Chapter 4](B9780080571157500042.xhtml) presents a reconstruction of GPS !!!(span) {:.smallcaps} , the General Problem Solver.
The implementation follows the STRIPS !!!(span) {:.smallcaps} approach.

[Chapter 5](B9780080571157500054.xhtml) describes ELIZA !!!(span) {:.smallcaps} , a program that mimics human dialogue.
This is followed by a chapter that generalizes some of the techniques used in GPS !!!(span) {:.smallcaps} and ELIZA !!!(span) {:.smallcaps} and makes them available as tools for use in subsequent programs.

[Chapter 7](B9780080571157500078.xhtml) covers STUDENT !!!(span) {:.smallcaps} , a program that solves high-school-level algebra word problems.

[Chapter 8](B978008057115750008X.xhtml) develops a small subset of the MACSYMA !!!(span) {:.smallcaps} program for doing symbolic algebra, including differential and integral calculus.
It may be skipped by those who shy away from heavy mathematics.

**[Part III](partiii.xhtml)** detours from AI for a moment to present some general tools for more efficient programming.
The reader who masters the material in this part can be considered an advanced Lisp programmer.

[Chapter 9](B9780080571157500091.xhtml) is a detailed study of efficiency techniques, concentrating on caching, indexing, compilation, and delaying computation.
[Chapter 10](B9780080571157500108.xhtml) covers lower-level efficiency issues such as using declarations, avoiding garbage generation, and choosing the right data structure.

[Chapter 11](B978008057115750011X.xhtml) presents the Prolog language.
The aim is two-fold: to show how to write an interpreter for another language, and to introduce the important features of Prolog, so that they can be used where appropriate.
[Chapter 12](B9780080571157500121.xhtml) shows how a compiler for Prolog can be 20 to 200 times faster than the interpreter.

[Chapter 13](B9780080571157500133.xhtml) introduces object-oriented programming in general, then explores the Common Lisp Object System (CLOS).

[Chapter 14](B9780080571157500145.xhtml) discusses the advantages and limitations of both logic-oriented and object-oriented programming, and develops a knowledge representation formalism using all the techniques of [part III](partiii.xhtml).

**[Part IV](partiv.xhtml)** covers some advanced AI programs.

[Chapter 15](B9780080571157500157.xhtml) uses the techniques of [part III](partiii.xhtml) to come up with a much more efficient implementation of MACSYMA !!!(span) {:.smallcaps} . It uses the idea of a canonical form, and replaces the very general rewrite rule approach with a series of more specific functions.

[Chapter 16](B9780080571157500169.xhtml) covers the EMYCIN !!!(span) {:.smallcaps} expert system shell, a backward chaining rule-based system based on certainty factors.
The MYCIN !!!(span) {:.smallcaps} medical expert system is also covered briefly.

[Chapter 17](B9780080571157500170.xhtml) covers the Waltz line-labeling algorithm for polyhedra (using Huffman-Clowes labels).
Different approaches to constraint propagation and backtracking are discussed.

[Chapter 18](B9780080571157500182.xhtml) presents a program that plays an excellent game of Othello.
The technique used, alpha-beta searching, is appropriate to a wide variety of two-person games.

[Chapter 19](B9780080571157500194.xhtml) is an introduction to natural language processing.
It covers context-free grammar, top-down and bottom-up parsing, chart parsing, and some semantic interpretation and preferences.

[Chapter 20](B9780080571157500200.xhtml) extends the linguistic coverage of the previous chapter and introduces logic grammars, using the Prolog compiler developed in [chapter 11](B978008057115750011X.xhtml).

[Chapter 21](B9780080571157500212.xhtml) is a fairly comprehensive grammar of English using the logic grammar formalism.
The problems of going from a simple idea to a realistic, comprehensive program are discussed.

**[Part V](partv.xhtml)** includes material that is peripheral to AI but important for any serious Lisp programmer.

[Chapter 22](B9780080571157500224.xhtml) presents the Scheme dialect of Lisp.
A simple Scheme interpreter is developed, then a properly tail-recursive interpreter, then an interpreter that explicitly manipulates continuations and supports `call/cc`.
[Chapter 23](B9780080571157500236.xhtml) presents a Scheme compiler.

[Chapter 24](B9780080571157500248.xhtml) presents the features that are unique to American National Standards Institute (ANSI) Common Lisp.
This includes the `loop` macro, as well as error handling, pretty printing, series and sequences, and the package facility.

[Chapter 25](B978008057115750025X.xhtml) is a guide to troubleshooting and debugging Lisp programs.

The bibliography lists over 200 sources, and there is a comprehensive index.
In addition, the appendix provides a directory of publicly available Lisp programs.

## How to Use This Book
{:#s0025}
{:.h1hd}

The intended audience for this book is broad: anyone who wants to become an advanced Lisp programmer, and anyone who wants to be an advanced AI practitioner.
There are several recommended paths through the book:
!!!(p) {:.para_fl}

*  *In an Introductory AI Course:* Concentrate on parts I and II, and at least one example from [part IV](partiv.xhtml).

*  *In an Advanced AI Programming Course:* Concentrate on parts I, II and IV, skipping chapters that are of less interest and adding as much of [part III](partiii.xhtml) as time permits.

*  *In an Advanced Programming Languages Course:* Concentrate on parts I and V, with selections from [part III](partiii.xhtml).
Cover [chapters 11](B978008057115750011X.xhtml) and [13](B9780080571157500133.xhtml) if similar material is not presented with another text.

*  *For the Professional Lisp Programmer:* Read as much of the book as possible, and refer back to it often.
[Part III](partiii.xhtml) and [chapter 25](B978008057115750025X.xhtml) are particularly important.

## Supplementary Texts and Reference Books
{:#s0030}
{:.h1hd}

The definitive reference source is Steele's *Common Lisp the Language*.
From 1984 to 1990, this unambiguously defined the language Common Lisp.
However, in 1990 the picture became more complicated by the publication of *Common Lisp the Language*, 2d edition.
This book, also by Steele, contains the recommendations of ANSI subcommittee X3J13, whose charter is to define a standard for Lisp.
These recommendations include many minor changes and clarifications, as well as brand new material on object-oriented programming, error condition handling, and the loop macro.
The new material doubles the size of the book from 465 to 1029 pages.
!!!(p) {:.para_fl}

Until the ANSI recommendations are formally accepted, Common Lisp users are in the unfortunate situation of having two distinct and incompatible standards: "original" Common Lisp and ANSI Common Lisp.
Most of the code in this book is compliant with both standards.
The most significant use of an ANSI function is the `loop` macro.
The ANSI `map-into`, `complement`, and `reduce` functions are also used, although rarely.
Definitions for all these functions are included, so even those using an "original" Common Lisp system can still run all the code in the book.

While *Common Lisp the Language* is the definitive standard, it is sometimes terse and can be difficult for a beginner.
*Common Lisp: the Reference*, published by Franz Inc., offers complete coverage of the language with many helpful examples.
*Common LISPcraft*, by Robert Wilensky, and *Artificial Intelligence Programming*, by Charniak et al., also include brief summaries of the Common Lisp functions.
They are not as comprehensive, but that can be a blessing, because it can lead the reader more directly to the functions that are important (at least in the eyes of the author).

It is a good idea to read this book with a computer at hand, to try out the examples and experiment with examples of your own.
A computer is also handy because Lisp is self-documenting, through the functions `apropos`, `describe`, and `documentation`.
Many implementations also provide more extensive documentation through some kind of 'help' command or menu.

The five introductory Lisp textbooks I recommend are listed below.
The first is more elementary than the others.

*  *Common Lisp: A Gentle Introduction to Symbolic Computation* by David Touretzky.
Most appropriate for beginners, including those who are not computer scientists.

*  *A Programmer's Guide to Common Lisp* by Deborah G.
Tatar.
Appropriate for those with experience in another programming language, but none in Lisp.

*  *Common LISPcraft* by Robert Wilensky.
More comprehensive and faster paced, but still useful as an introduction as well as a reference.

*  *Common Lisp* by Wade L.
Hennessey.
Somewhat hit-and-miss in terms of the topics it covers, but with an enlightened discussion of implementation and efficiency issues that do not appear in the other texts.

*  *LISP* (3d edition) by Patrick H.
Winston and Bertold Horn.
Covers the most ground in terms of programming advice, but not as comprehensive as a reference.
May be difficult for beginners.
Includes some AI examples.

While it may be distracting for the beginner to be continually looking at some reference source, the alternative-to have this book explain every new function in complete detail as it is introduced-would be even more distracting.
It would interrupt the description of the AI programs, which is what this book is all about.

There are a few texts that show how to write AI programs and tools, but none that go into the depth of this book.
Nevertheless, the expert AI programmer will want to be familiar with all the following texts, listed in rough order of increasing sophistication:

*  *LISP* (3d edition).
(See above.)

*  *Programming Paradigms in Lisp* by Rajeev Sangal.
Presents the different styles of programming that Lisp accommodates, illustrating them with some useful AI tools.

*  *Programming for Artificial Intelligence* by Wolfgang Kreutzer and Bruce McKenzie.
Covers some of the basics of rule-based and pattern-matching systems well, but covers Lisp, Prolog, and Smalltalk, and thus has no time left for details in any of the languages.

*  *Artificial Intelligence Programming* (2d edition) by Eugene Charniak, Christopher Riesbeck, Drew McDermott, and James Meehan.
Contains 150 pages of Lisp overview, followed by an advanced discussion of AI tools, but no actual AI programs.

*  *AI in Practice: Examples in Pop-11* by Allan Ramsey and Rosalind Barrett.
Advanced, high-quality implementations of five AI programs, unfortunately using a language that has not gained popularity.

The current text combines the virtues of the last two entries: it presents both actual AI programs and the tools necessary to build them.
Furthermore, the presentation is in an incremental fashion, with simple versions presented first for clarity, followed by more sophisticated versions for completeness.

## A Note on Exercises
{:#s0035}
{:.h1hd}

Sample exercises are provided throughout.
Readers can test their level of understanding by faithfully doing the exercises.
The exercises are graded on the scale [s], [m], [h], [d], which can be interpreted either as a level of difficulty or as an expected time it will take to do the exercise:
!!!(p) {:.para_fl}

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| Code | Difficulty | Time to Do |
| [s] | Simple | Seconds |
| [m] | Medium | Minutes |
| [h] | Hard | Hours |
| [d] | Difficult | Days |

The time to do the exercise is measured from the point that the concepts have been well understood.
If the reader is unclear on the underlying concepts, it might take hours of review to understand a [m] problem.
Answers to the exercises can be found in a separate section at the end of each chapter.

## Acknowledgments
{:#s0010}
{:.h1hd}

A great many people contributed to this book.
First of all I would like to thank my students at USC and Berkeley, as well as James Martin's students at Colorado and Michael Pazzani's students at Irvine, who course-tested earlier versions of this book.
Useful suggestions, corrections, and additions were made by:
!!!(p) {:.para_fl}

Nina Amenta (Berkeley), Ray S.
Babcock and John Paxton (Montana State), Bryan A.
Bentz (BBN), Mary P.
Boelk (Johnson Controls), Michael Braverman (Berkeley), R.
Chandrasekar and M.
Sasikumar (National Centre for Software Technology, Bombay), Mike Clancy (Berkeley), Michael Covington (Georgia), Bruce D'Ambrosio (Oregon State), Piew Datta (Irvine), Shawn Dettrey (USC), J.
A.
Durieux (AI Engineering BV, Amsterdam), Joseph Faletti (ETS), Paul Fuqua (Texas Instruments), Robert Goldman (Tulane), Marty Hall (Johns Hopkins), Marti Hearst (Berkeley), Jim Hendler (Maryland), Phil Laird (NASA), Raymond Lang (Tulane), David D.
Loeffler (MCC), George Luger (New Mexico), Rob MacLachlan (CMU), Barry Margolin (Thinking Machines), James Mayfield (UMBC), Sanjay Manchandi (Arizona), Robert McCartney (Connecticut), James Meehan (DEC), Andrew L.
Ressler, Robert S.
Rist (University of Technology, Sydney), Paul Snively (Apple), Peter Van Roy (Berkeley), David Gumby Wallace (Cygnus), and Jeff Wu (Colorado).

Sam Dooley and Eric Wefald both wrote Othello-playing programs without which I would not have written [chapter 18](B9780080571157500182.xhtml).
Eric also showed me Aristotle's quotes on means-ends analysis.
Tragically, Eric died in August 1989.
He is sorely missed by his friends and colleagues.
Richard Fateman made suggestions for [chapter 8](B978008057115750008X.xhtml), convinced me to write [chapter 15](B9780080571157500157.xhtml), and, with help from Peter Klier, wrote a substantial program from which I adapted some code for that chapter.
Charley Cox (Franz Inc.), Jamie Zawinski (Lucid Inc.), and Paul Fuqua (Texas Instruments) explained the inner workings of their respective companies' compilers.
Mike Harrison, Paul Hilfinger, Marc Luria, Ethan Munson, and Stephan Slade helped with LA !!!(span) {:.smallcaps} TE !!!(span) {:.smallcaps} X.
Narciso Jarimillo tested all the code and separated it into the files that are available to the reader (see page 897).

During the writing of this book I was supported by a grant from the Defense Advanced Research Projects Agency (DoD), Arpa Order No.
4871, monitored by Space and Naval Warfare Systems Command under Contract N00039-84-C-0089.
Special thanks to DARPA and to Robert Wilensky and the rest of my colleagues and students at Berkeley for providing a stimulating environment for research, programming, and writing.

Finally, thanks to Mike Morgan and Yonie Overton for overseeing the production of the book and encouraging me to finish on time.

----------------------

[1](#xfn0010) This does not imply that the programs chosen are the best of all AI programs-just that they are representative.
!!!(p) {:.ftnote1}

Part I
Introduction to Common Lisp
!!!(p) {:.parttitle}

# Chapter 1
## Introduction to Lisp
{:.chaptitle}

> You think you know when you learn, are more sure when you can write, even more when you can teach, but certain when you can program.

> -Alan Perlis

> Yale University computer scientist

This chapter is for people with little or no experience in Lisp.
Readers who feel confident in their Lisp programming ability can quickly skim the chapter or skip it entirely.
This chapter necessarily moves quickly, so those with little programming experience, or any reader who finds this chapter tough going, should seek out a supplementary introductory text.
My recommendations are in the preface.

Computers allow one to carry out computations.
A word processing program deals with words while a calculator deals with numbers, but the principles are the same.
In both cases, you provide the input (words or numbers) and specify the operations (such as deleting a word or adding two numbers) to yield a result (a completed document or calculation).

We will refer to anything that can be represented in the memory of a computer as a *computational object,* or just an *object.* So, words, paragraphs, and numbers can be objects.
And because the operations (deleting and adding) must be represented somewhere in the computer's memory, they are objects, too.

Normally, the distinction between a computer "user" and a computer "programmer" is that the user provides new input, or data (words or numbers), while the programmer defines new *operations*, or programs, as well as new *types* of data.
Every new object, be it datum or operation, must be defined in terms of previously defined objects.
The bad news is that it can be quite tedious to get these definitions right.
The good news is that each new object can in turn be used in the definition of future objects.
Thus, even complex programs can be built out of smaller, simpler objects.
This book covers a number of typical AI problems, showing how each problem can be broken down into manageable pieces, and also how each piece can be described in the programming language Common Lisp.
Ideally, readers will learn enough through studying these examples to attack new AI problems with style, grace, and success.

Let's consider a simple example of a computation: finding the sum of two numbers, let's say 2 and 2.
If we had a calculator handy, we would type "2 + 2 =" and see the answer displayed.
On a calculator using reverse Polish notation, we would have to type "22+" to see the same answer.
In Lisp, as with the calculator, the user carries out an interactive dialog with the computer by typing in an expression and seeing the computer print the value of that expression.
This interactive mode is different from many other programming languages that only offer a batch mode, wherein an entire program is compiled and run before any output can be seen.

We start up a pocket calculator by flipping the on/off switch.
The Lisp program must also be started, but the details vary from one computer to another, so I can't explain how your Lisp will work.
Assuming we have managed to start up Lisp, we are likely to see a *prompt* of some kind.
On my computer, Lisp types "`>`" to indicate it is ready to accept the next computation.
So we are faced with a screen that looks like this:

```lisp
  >
```

We may now type in our computation and see the result displayed.
It turns out that the Lisp convention for arithemtic expressions is slightly different: a computation consists of a parenthesized list with the operation name first, followed by any number of operands, or arguments.
This is called *prefix notation.*

```lisp
  >(+ 2 2)
  4
  >
```

We see that Lisp has printed the answer, 4, and then another prompt, >, to indicate it is ready for the next computation.
Throughout this book, all Lisp expressions will be displayed in `typewriter` font.
Text on the same line as the ">" prompt is input typed by the user, and text following it is output printed by the computer.
Usually, input that is typed by the programmer will be in `lowercase` letters, while output that is printed back by the computer will be in `UPPERCASE` letters.
Of course, with symbols like + and 4 there is no difference.

To save space on the page, the output will sometimes be shown on the same line as the input, separated by an arrow (=>), which can be read as "evaluates to," and can also be thought of as standing for the return or enter key that the user presses to complete the input:

```lisp
  > (+ 2 2) => 4
```

One advantage of parenthesized prefix notation is that the parentheses clearly mark the beginning and end of an expression.
If we want, we can give + more than two arguments, and it will still add them all:

```lisp
  > (+ 1 2 3 4 5 6 7 8 9 10) => 55
```

This time we try (9000 + 900 + 90 + 9) - (5000 + 500 + 50 + 5):

```lisp
  > (- (+ 9000 900 90 9) (+ 5000 500 50 5)) => 4444
```

This example shows that expressions can be nested.
The arguments to the - function are parenthesized lists, while the arguments to each `+` are atoms.
The Lisp notation may look unusual compared to standard mathematical notation, but there are advantages to this notation; since Lisp expressions can consist of a function followed by any number of arguments, we don't have to keep repeating the `"+."` More important than the notation is the rule for evaluation.
In Lisp, lists are evaluated by first evaluating all the arguments, then applying the function to the arguments, thereby Computing the result.
This rule is much simpler than the rule for evaluating normal mathematical expressions, where there are many conventions to remember, such as doing multiplications and divisions before sums and differences.
We will see below that the actual Lisp evaluation rule is a little more complicated, but not much.

Sometimes programmers who are familiar with other languages have preconceptions that make it difficult for them to learn Lisp.
For them, three points are worth stressing here.
First, many other languages make a distinction between statements and expressions.
An expression, like `2 + 2`, has a value, but a statement, like `x = 2 + 2`, does not.
Statements have effects, but they do not return values.
In Lisp, there is no such distinction: every expression returns a value.
It is true that some expressions have effects, but even those expressions also return values.

Second, the lexical rules for Lisp are much simpler than the rules for other languages.
In particular, there are fewer punctuation characters: only parentheses, quote marks (single, double, and backward), spaces, and the comma serve to separate symbols from each other.
Thus, while the statement `y=a*x+3` is analyzed as seven separate tokens in other languages, in Lisp it would be treated as a single symbol.
To get a list of tokens, we would have to insert spaces: `(y = a * x + 3)`.[1](#fn0010)

Third, while many languages use semicolons to delimit statements, Lisp has no need of semicolons, since expressions are delimited by parentheses.
Lisp chooses to use semicolons for another purpose-to mark the beginning of a comment, which lasts until the end of the line:

```lisp
  >(+ 2 2) ; this is a comment
  4
```

## 1.1 Symbolic Computation
{:#s0010}
{:.h1hd}

All we've done so far is manipulate numbers in the same way a simple pocket calculator would.
Lisp is more useful than a calculator for two main reasons.
First, it allows us to manipulate objects other than numbers, and second, it allows us to define new objects that might be useful in subsequent computations.
We will examine these two important properties in turn.

Besides numbers, Lisp can represent characters (letters), strings of characters, and arbitrary symbols, where we are free to interpret these symbols as referring to things outside the world of mathematics.
Lisp can also build nonatomic objects by combining several objects into a list.
This capability is fundamental and well supported in the language; in fact, the name Lisp is short for LISt Processing.

Here's an example of a computation on lists:

```lisp
  > (append '(Pat Kim) '(Robin Sandy)) => (PAT KIM ROBIN SANDY)
```

This expression appends together two lists of names.
The rule for evaluating this expression is the same as the rule for numeric calculations: apply the function (in this case append) to the value of the arguments.

The unusual part is the quote mark `(')`, which serves to block the evaluation of the following expression, returning it literally.
If we just had the expression (`Pat Kim),` it would be evaluated by considering `Pat` as a function and applying it to the value of the expression `Kim.` This is not what we had in mind.
The quote mark instructs Lisp to treat the list as a piece of data rather than as a function call:

```lisp
  >'(Pat Kim) (PAT KIM)
```

In other computer languages (and in English), quotes usually come in pairs: one to mark the beginning, and one to mark the end.
In Lisp, a single quote is used to mark the beginning of an expression.
Since we always know how long a single expression is-either to the end of an atom or to the matching parenthesis of a list-we don't need an explicit punctuation mark to tell us where the expression ends.
Quotes can be used on lists, as in `'(Pat Kim)`, on symbols as in `'Robin`, and in fact on anything else.
Here are some examples:

```lisp
  > 'John => JOHN
  > '(John Q Public) => (JOHN Q PUBLIC)
  > '2 => 2
  > 2 => 2
  > '(+ 2 2) => (+ 2 2)
  > (+ 2 2) 4
  > John => *Error: JOHN is not a bound variable*
  > (John Q Public) => *Error: JOHN is not a function*
```

Note that `'2` evaluates to `2` because it is a quoted expression, and `2` evaluates to `2` because numbers evaluate to themselves.
Same result, different reason.
In contrast, '`John` evaluates to `John` because it is a quoted expression, but evaluating `John` leads to an error, because evaluating a symbol means getting the value of the symbol, and no value has been assigned to `John.`

Symbolic computations can be nested and even mixed with numeric computations.
The following expression builds a list of names in a slightly different way than we saw before, using the built-in function `list`.
We then see how to find the number of elements in the list, using the built-in function `length:`

```lisp
  > (append '(Pat Kim) (list '(John Q Public) 'Sandy))
  (PAT KIM (JOHN Q PUBLIC) SANDY)
  > (length (append '(Pat Kim) (list '(John Q Public) 'Sandy)))
  4
```

There are four important points to make about symbols:

*  First, it is important to remember that Lisp does not attach any external significance to the objects it manipulates.
For example, we naturally think of (`Robin Sandy`) as a list of two first names, and (`John Q Public`) as a list of one person's first name, middle initial, and last name.
Lisp has no such preconceptions.
To Lisp, both `Robin` and `xyzzy` are perfectly good symbols.

*  Second, to do the computations above, we had to know that `append, length`, and + are defined functions in Common Lisp.
Learning a language involves remembering vocabulary items (or knowing where to look them up) as well as learning the basic rules for forming expressions and determining what they mean.
Common Lisp provides over 700 built-in functions.
At some point the reader should flip through a reference text to see what's there, but most of the important functions are presented in part I of this book.

*  Third, note that symbols in Common Lisp are not case sensitive.
By that I mean that the inputs `John, john,` and `jOhN` all refer to the same symbol, which is normally printed as `JOHN.`[2](#fn0015)

*  Fourth, note that a wide variety of characters are allowed in symbols: numbers, letters, and other punctuation marks like `'+'` or `'!'` The exact rules for what constitues a symbol are a little complicated, but the normal convention is to use symbols consisting mostly of letters, with words separated by a dash `(-)`, and perhaps with a number at the end.
Some programmers are more liberal in naming variables, and include characters like `'?!$/<=>'`.
For example, a function to convert dollars to yen might be named with the symbol `$ - to -yen` or `$ ->yen` in Lisp, while one would use something like `DollarsToYen, dollars_to_yen` or `dol2yen` in Pascal or C.
There are a few exceptions to these naming conventions, which will be dealt with as they come up.

## 1.2 Variables
{:#s0015}
{:.h1hd}

We have seen some of the basics of symbolic computation.
Now we move on to perhaps the most important characteristic of a programming language: the ability to define new objects in terms of other s, and to name these objects for future use.
Here symbols again play an important role-they are used to name variables.
A variable can take on a value, which can be any Lisp object.
One way to give a value to a variable is with setf :

```lisp
  > (setf p '(John Q Public)) => (JOHN Q PUBLIC)
  > p => (JOHN Q PUBLIC)
  > (setf x 10) => 10
  > (+ x x) => 20
  > (+ x (length p)) => 13
```

After assigning the value (`John Q Public`) to the variable named `p`, we can refer to the value with the name `p`.
Similarly, after assigning a value to the variable named `x`, we can refer to both `x` and `p`.

Symbols are also used to name functions in Common Lisp.
Every symbol can be used as the name of a variable or a function, or both, although it is rare (and potentially confusing) to have symbols name both.
For example, `append` and `length` are symbols that name functions but have no values as variables, and `pi` does not name a function but is a variable whose value is 3.1415926535897936 (or thereabout).

## 1.3 Special Forms
{:#s0020}
{:.h1hd}

The careful reader will note that `setf` violates the evaluation rule.
We said earlier that functions like `+`, - and `append` work by first evaluating all their arguments and then applying the function to the result.
But `setf` doesn't follow that rule, because `setf` is not a function at all.
Rather, it is part of the basic syntax of Lisp.
Besides the syntax of atoms and function calls, Lisp has a small number of syntactic expressions.
They are known as *special forms.* They serve the same purpose as statements in other programming languages, and indeed have some of the same syntactic markers, such as `if` and `loop`.
There are two main differences between Lisp's syntax and other languages.
First, Lisp's syntactic forms are always lists in which the first element is one of a small number of privileged symbols.
`setf` is one of these symbols, so (`setf x 10`) is a special form.
Second, special forms are expressions that return a value.
This is in contrast to statements in most languages, which have an effect but do not return a value.

In evaluating an to expression like `(setf x (+ 1 2)`), we set the variable named by the symbol `x` to the value of `(+ 1 2)`, which is `3`.
If `setf` were a normal function, we would evaluate both the symbol `x` and the expression `(+ 1 2)` and do something with these two values, which is not what we want at all.
`setf` is called a special form because it does something special: if it did not exist, it would be impossible to write a function that assigns a value to a variable.
The philosophy of Lisp is to provide a small number of special forms to do the things that could not otherwise be done, and then to expect the user to write everthing else as functions.

The term *special form* is used confusingly to refer both to symbols like `setf` and expressions that start with them, like `(setf x 3)`.
In the book *Common LISPcraft,* Wilensky resolves the ambiguity by calling `setf` a *special function,* and reserving the term *special form* for (`setf x 3`).
This terminology implies that `setf` is just another function, but a special one in that its first argument is not evaluated.
Such a view made sense in the days when Lisp was primarily an interpreted language.
The modem view is that `setf` should not be considered some kind of abnormal function but rather a marker of special syntax that will be handled specially by the compiler.
Thus, the special form `(setf x (+ 2 1))` should be considered the equivalent of `x = 2 + 1` in `C`.
When there is risk of confusion, we will call `setf` a *special form operator* and `(setf x 3)` a *special form expression.*

It turns out that the quote mark is just an abbreviation for another special form.
The expression '*x* is equivalent to `(quote *x*)`, a special form expression that evaluates to *x.* The special form operators used in this chapter are:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `defun` | define function |
| `defparameter` | define special variable |
| `setf` | set variable or field to new value |
| `let` | bind local variable(s) |
| `case` | choose one of several alternatives |
| `if` | do one thing or another, depending on a test |
| `function (#')` | refer to a function |
| `quote (')` | introduce constant data |

## 1.4 Lists
{:#s0025}
{:.h1hd}

So far we have seen two functions that operate on lists: `append` and l`ength.` Since lists are important, let's look at some more list processing functions:

```lisp
  > p => (JOHN Q PUBLIC)
  > (first p) JOHN
  > (rest p) => (Q PUBLIC)
  > (second p) => Q
  > (third p) => PUBLIC
  > (fourth p) => NIL
  > (length p) => 3
```

The functions `first, second, third,` and `fourth` are aptly named: `first` returns the first element of a list, `second` gives you the second element, and so on.
The function `rest` is not as obvious; its name stands for "the rest of the list after the first element." The symbol `nil` and the form `()` are completely synonymous; they are both representations of the empty list.
`nil` is also used to denote the "false" value in Lisp.
Thus, `(fourth p)` is `nil` because there is no fourth element of `p.` Note that lists need not be composed only of atoms, but can contain sublists as elements:

```lisp
  > (setf x '((1st element) 2 (element 3) ((4)) 5))
  > ((1ST ELEMENT) 2 (ELEMENT 3) ((4)) 5)
  > (length x) => 5
  > (first x) => (1ST ELEMENT)
  > (second x) => 2
  > (third x) => (ELEMENT 3)
  > (fourth x) => ((4))
  > (first (fourth x)) => (4)
  > (first (first (fourth x))) => 4
  > (fifth x) => 5
  > (first x) => (1ST ELEMENT)
  > (second (first x)) => ELEMENT
```

So far we have seen how to access parts of lists.
It is also possible to build up new lists, as these examples show:

```lisp
  > p => (JOHN Q PUBLIC)
  > (cons 'Mr p) => (MR JOHN Q PUBLIC)
  > (cons (first p) (rest p)) => (JOHN Q PUBLIC)
  > (setf town (list 'Anytown 'USA)) => (ANYTOWN USA)
  > (list p 'of town 'may 'have 'already 'won!) =>
  ((JOHN Q PUBLIC) OF (ANYTOWN USA) MAY HAVE ALREADY WON!)
  > (append p '(of) town '(may have already won!)) =>
  (JOHN Q PUBLIC OF ANYTOWN USA MAY HAVE ALREADY WON!)
  > p => (JOHN Q PUBLIC)
```

The function cons stands for "construct." It takes as arguments an element and a list,[3](#fn0020) and constructs a new list whose first is the element and whose rest is the original list.
`list` takes any number of elements as arguments and returns a new list containing those elements in order.
We've already seen `append,` which is similar to `list`; it takes as arguments any number of lists and appends them all together, formingone biglist.
Thus, the arguments to `append` must be lists, while the arguments to `list` may be lists or atoms.
It is important to note that these functions create new lists; they don't modify old ones.
When we say `(append p q`), the effect is to create a brand new list that starts with the same elements that were in `p.
p` itself remains unchanged.

Now let's move away from abstract functions on lists, and consider a simple problem: given a person's name in the form of a list, how might we extract the family name?
For `(JOHN Q PUBLIC)` wecouldjust use the function `third`, but that wouldn't work for someone with no middle name.
There is a function called `last` in Common Lisp; perhaps that would work.
We can experiment:

```lisp
  > (last p) => (PUBLIC)
  > (first (last p)) => PUBLIC
```

It turns out that `last` perversely returns a list of the last element, rather than the last element itself.[4](#fn0025) Thus we need to combine `first` and `last` to pick out the actual last element.
We would like to be able to save the work we've done, and give it a proper description, like `last-name`.
We could use `setf` to save the last name of `p`, but that wouldn't help determine any other last name.
Instead we want to define a new function that computes the last name of *any* name that is represented as a list.
The next section does just that.

## 1.5 Defining New Functions
{:#s0030}
{:.h1hd}

The special form `defun` stands for "define function." It is used here to define a new function called `last-name`:

```lisp
  (defun last-name (name)
     "Select the last name from a name represented as a list."
     (first (last name)))
```

We give our new function the name `last-name.` It has a *parameter list* consisting of a single parameter: (`name`).
This means that the function takes one argument, which we will refer to as `name.` It also has a *documentation string* that states what the function does.
This is not used in any computation, but documentation strings are crucial tools for debugging and understanding large systems.
The body of the definition is `(first (last name))`, which is what we used before to pick out the last name of `p`.
The difference is that here we want to pick out the last name of any `name,` not just of the particular name `p`.

In general, a function definition takes the following form (where the documentation string is optional, and all other parts are required):

  `(defun`*function-name* (*parameter...*)

     "*documentation string*"

     *function-body...*)

The function name must be a symbol, the parameters are usually symbols (with some complications to be explained later), and the function body consists of one or more expressions that are evaluated when the function is called.
The last expression is returned as the value of the function call.

Once we have defined `last-name,` we can use it just like any other Lisp function:

```lisp
  > (last-name p) => PUBLIC
  > (last-name '(Rear Admiral Grace Murray Hopper)) => HOPPER
  > (last-name '(Rex Morgan MD)) => MD
  > (last-name '(Spot)) => SPOT
  > (last-name '(Aristotle)) => ARISTOTLE
```

The last three examples point out an inherent limitation of the programming enterprise.
Whenwesay `(defun last-name...)` we are not really defining what it means for a person to have a last name; we are just defining an operation on a representation of names in terms of lists.
Our intuitions-that MD is a title, Spot is the first name of a dog, and Aristotle lived before the concept of last name was invented-are not represented in this operation.
However, we could always change the definition of `last-name` to incorporate these problematic cases.

We can also define the function `first-name.` Even though the definition is trivial (it is the same as the function `first),` it is still good practice to define `first-name` explicitly.
Then we canuse the function `first-name` when we are dealing with names, and `first` when we are dealing with arbitrary lists.
The computer will perform the same operation in each case, but we as programmers (and readers of programs) will be less confused.
Another advanatge of defining specific functions like `first-name` is that if we decide to change the representation of names we will only have to change the definition of `first-name.` This is a much easier task than hunting through a large program and changing the uses of `first` that refer to names, while leaving other uses alone.

```lisp
  (defun first-name (name)
     "Select the first name from a name represented as a list."
     (first name))
  > p => (JOHN Q PUBLIC)
  > (first-name p) => JOHN
  > (first-name '(Wilma Flintstone)) => WILMA
  > (setf names '((John Q Public) (Malcolm X)
                               (Admiral Grace Murray Hopper) (Spot)
                               (Aristotle) (A A Milne) (Z Z Top)
                               (Sir Larry Olivier) (Miss Scarlet))) =>
  ((JOHN Q PUBLIC) (MALCOLM X) (ADMIRAL GRACE MURRAY HOPPER)
    (SPOT) (ARISTOTLE) (A A MILNE) (Z Z TOP) (SIR LARRY OLIVIER)
    (MISS SCARLET))
  > (first-name (first names)) => JOHN
```

In the last expression we used the function `first` to pick out the first element in a list of names, and then the function `first-name` to pick out the first name of that element.
We could also have said `(first (first names))` or even `(first (first-name names))` and still have gotten `JOHN,` but we would not be accurately representing what is being considered a name and what is being considered a list of names.

## 1.6 Using Functions
{:#s0035}
{:.h1hd}

One good thing about defining a list of names, as we did above, is that it makes it easier to test our functions.
Consider the followingexpression, which can be used to test the `last-name` function:

```lisp
  > (mapcar #'last-name names)
  (PUBLIC X HOPPER SPOT ARISTOTLE MILNE TOP OLIVIER SCARLET)
```

The funny `#'` notation maps from the name of a function to the function itself.
This is analogous to `'x` notation.
The built-in function mapca r is passed two arguments, a function and a list.
It returns a list built by calling the function on every element of the input list.
In other words, the `mapcar` call above is equivalent to:

```lisp
  (list (last-name (first names))
            (1ast-name (second names))
            (last-name (third names))
             ...)
```

`mapcar's` name cornes from the fact that it "maps" the function across each of the arguments.
The `car` part of the name refers to the Lisp function `car`, an old name for `first`.
`cdr` is the old name for `rest`.
The names stand for "contents of the address register" and "contents of the decrement register," the instructions that were used in the first implementation of Lisp on the IBM 704.
I'm sure you'll agree that `first` and `rest` are much better names, and they will be used instead of `car` and `cdr` whenever we are talking about lists.
However, we will continue to use `car` and `cdr` on occasion when we are considering a pair of values that are not considered as a list.
Beware that some programmers still use `car` and `cdr` for lists as well.

Here are some more examples of `mapcar`:

```lisp
  > (mapcar #'- '(1 2 3 4)) => (-l -2 -3 -4)
  > (mapcar #'+ '(1 2 3 4) '(10 20 30 40)) => (11 22 33 44)
```

This last example shows that `mapcar` can be passed three arguments, in which case the first argument should be a binary function, which will be applied to corresponding elements of the other two lists.
In general, `mapcar` expects an *n*-ary function as its first argument, followed by *n* lists.
It first applies the function to the argument list obtained by collecting the first element of each list.
Then it applies the function to the second element of each list, and so on, until one of the lists is exhausted.
It returns a list of all the function values it has computed.

Now that we understand `mapcar`, let's use it to test the `first-name` function:

```lisp
  > (mapcar #'first-name names)
  (JOHN MALCOLM ADMIRAL SPOT ARISTOTLE A Z SIR MISS)
```

We might be disappointed with these results.
Suppose we wanted a version of `first-name` which ignored titles like Admiral and Miss, and got to the "real" first name.
We could proceed as follows:

```lisp
  (defparameter *titles*
     '(Mr Mrs Miss Ms Sir Madam Dr Admiral Major General)
     "A list of titles that can appear at the start of a name.")
```

We've introduced another new special form, `defparameter,` which defines a parameter-a variable that does not change over the course of a computation, but that might change when we think of new things to add (like the French Mme or the military Lt.).
The `defparameter` form both gives a value to the variable and makes it possible to use the variable in subsequent function definitions.
In this example we have exercised the option of providing a documentation string that describes the variable.
It is a widely used convention among Lisp programmers to mark special variables by spelling their names with asterisks on either end.
This is just a convention; in Lisp, the asterisk is just another character that has no particular meaning.

We next give a new definition for `first-name`, which supersedes the previous definition.[5](#fn0030) This definition says that if the first word of the name is a member of the list of titles, then we want to ignore that word and return the `first-name` of the rest of the words in the name.
Otherwise, we use the first word, just as before.
Another built-in function, `member`, tests to see if its first argument is an element of the list passed as the second argument.

The special form `if` has the form `(if *test then-part else-part*)`.
There are many special forms for performing conditional tests in Lisp; `if` is the most appropriate for this example.
An `if` form is evaluated by first evaluating the *test* expression.
If it is true, the *then-part* is evaluated and returned as the value of the `if` form; otherwise the *else-part* is evaluated and returned.
While some languages insist that the value of a conditional test must be either `true` or `false`, Lisp is much more forgiving.
The test may legally evaluate to any value at all.
Only the value `nil` is considered false; all other values are considered true.
In the definition of `first-name` below, the function `member` will return a non-nil (hence true) value if the first element of the name is in the list of titles, and will return `nil` (hence false) if it is not.
Although all non-nil values are considered true, by convention the constant `t` is usually used to represent truth.

```lisp
  (defun first-name (name)
     "Select the first name from a name represented as a list."
     (if (member (first name) *titles*)
            (first-name (rest name))
            (first name)))
```

When we map the new `first-name` over the list of names, the results are more encouraging.
In addition, the function gets the "right" result for `'(Madam Major General Paul a Jones)` by dropping off titles one at a time.

```lisp
  > (mapcar #'first-name names)
  (JOHN MALCOLM GRACE SPOT ARISTOTLE A Z LARRY SCARLET)
  > (first-name '(Madam Major General Paul a Jones))
  PAULA
```

We can see how this works by *tracing* the execution of `first-name`, and seeing the values passed to and returned from the function.
The special forms trace and untrace are used for this purpose.

```lisp
  > (trace first-name)
  (FIRST-NAME)
  > (first-name '(John Q Public))
  (1 ENTER FIRST-NAME: (JOHN Q PUBLIC))
  (1 EXIT FIRST-NAME: JOHN)
  JOHN
```

When `first-name` is called, the definition is entered with the single argument, `name,` taking on the value `(JOHN Q PUBLIC)`.
The value returned is `JOHN`.
Trace prints two lines indicating entry and exit from the function, and then Lisp, as usual, prints the final result, `JOHN`.

The next example is more complicated.
The function `first-name` is used four times.
First, itis entered with `name` boundto `(Madam Major General Paula Jones).` The first element of this list is `Madam,` and since this is a member of the list of titles, the result is computed by calling `first-name` again on the rest of the name-`(Major General Paula Jones).` This process repeats two more times, and we finally enter fi`rst-name` with name bound to (`Paul a Jones`).
Since `Paula` is not a title, it becomes the result of this call to fi`rst-name,` and thus the result of all four calls, as trace shows.
Once we are happy with the workings of first`-name,` the special form `untrace` turns off tracing.

```lisp
  > (first-name '(Madam Major General Paula Jones)) =>
  (1 ENTER FIRST-NAME: (MADAM MAJOR GENERAL PAULA JONES))
    (2 ENTER FIRST-NAME: (MAJOR GENERAL PAULA JONES))
      (3 ENTER FIRST-NAME: (GENERAL PAULA JONES))
        (4 ENTER FIRST-NAME: (PAULA JONES))
        (4 EXIT FIRST-NAME: PAULA)
      (3 EXIT FIRST-NAME: PAULA)
    (2 EXIT FIRST-NAME: PAULA)
  (1 EXIT FIRST-NAME: PAULA)
  PAULA
  > (untrace first-name) => (FIRST-NAME)
  > (first-name '(Mr Blue Jeans)) => BLUE
```

The function `first-name` is said to be *recursive* because its definition includes a call to itself.
Programmers who are new to the concept of recursion sometimes find it mysterious.
But recursive functions are really no different from nonrecursive ones.
Any function is required to return the correct value for the given input(s).
Another way to look at this requirement is to break it into two parts: a function must return a value, and it must not return any incorrect values.
This two-part requirement is equivalent to the first one, but it makes it easier to think about and design function definitions.

Next I show an abstract description of the `first-name` problem, to emphasize the design of the function and the fact that recursive solutions are not tied to Lisp in any way:

```lisp
  function first-name(name):
    if *the first element of name is a title*
       then *do something complicated to get the first-name*
       else *return the first element of the name*
```

This breaks up the problem into two cases.
In the second case, we return an answer, and it is in fact the correct answer.
We have not yet specified what to do in the first case.
But we do know that it has something to do with the rest of the name after the first element, and that what we want is to extract the first name out of those elements.
The leap of faith is to go ahead and use `first-name`, even though it has not been fully defined yet:

```lisp
  function first-name(name):
    if *the first element of name is a title*
       then *return the* first-name *of the rest of the name*
       else *return the first element of the name*
```

Now the first case in `first-name` is recursive, and the second case remains unchanged.
We already agreed that the second case returns the correct answer, and the first case only returns what `first-name` returns.
So `first-name` as a whole can only return correct answers.
Thus, we're halfway to showing that the function is correct; the other half is to show that it eventually returns some answer.
But every recursive call chops off the first element and looks at the rest, so for an *n*-element list there can be at most *n* recursive calls.
This completes the demonstration that the function is correct.
Programmers who learn to think this way find recursion to be a valuable tool rather than a confusing mystery.

## 1.7 Higher-Order Functions
{:#s0040}
{:.h1hd}

Functions in Lisp can not only be "called," or applied to arguments, they can also be manipulated just like any other kind of object.
A function that takes another function as an argument is called a *higher-order function.*`mapcar` is an example.
To demonstrate the higher-order-function style of programming, we will define a new function called `mappend.` It takes two arguments, a function and a list.
`mappend` maps the function over each element of the list and appends together all the results.
The first definition follows immediately from the description and the fact that the function `appl`y can be used to apply a function to a list of arguments.

```lisp
  (defun mappend (fn the-list)
     "Apply fn to each element of list and append the results."
     (apply #'append (mapcar fn the-list)))
```

Now we experiment a little to see how `appl`y and `mappend` work.
The first example applies the addition function to a list of four numbers.

```lisp
  > (apply #'+ '(1 2 3 4)) => 10
```

The next example applies append to a list of two arguments, where each argument is a list.
If the arguments were not lists, it would be an error.

```lisp
  > (apply #'append '((1 2 3) (a b c))) => (l 2 3 A B C)
```

Now we define a new function, `self-and-double`, and apply it to a variety of arguments.

```lisp
  > (defun self-and-double (x) (list x (+ x x)))
  > (self-and-double 3) => (3 6)
  > (apply #' self-and-double ' (3)) => (3 6)
```

If we had tried to apply `self-and-double` to a list of more than one argument, or to a list that did not contain a number, it would be an error, just as it would be an error to evaluate `(self-and-double 3 4`) or `(self-and-double 'Kim`).
Now let's return to the mapping functions:

```lisp
  > (mapcar #'self-and-double '(1 10 300)) => ((1 2) (10 20) (300 600))
  > (mappend #'self-and-double '(1 10 300)) => (1 2 10 20 300 600)
```

When `mapcar` is passed a function and a list of three arguments, it always returns a list of three values.
Each value is the result of calling the function on the respective argument.
In contrast, when `mappend` is called, it returns one big list, which is equal to all the values that `mapcar` would generate appended together.
It would be an error to call `mappend` with a function that didn't return lists, because `append` expects to see lists as its arguments.

Now consider the following problem: given a list of elements, return a list consisting of all the numbers in the original list and the negation of those numbers.
For example, given the list `(testing 1 2 3 test`), return `(1 -1 2 -2 3 -3`).
This problem can be solved very easily using `mappend` as a component:

```lisp
  (defun numbers-and-negations (input)
     "Given a list, return only the numbers and their negations."
     (mappend #' number-and-negation input))
  (defun number-and-negation (x)
     "If x is a number, return a list of x and -x."
     (if (numberp x)
            (list x (- x))
             nil))
  > (numbers-and-negations '(testing 1 2 3 test)) => (1 -1 2 -2 3 -3)
```

The alternate definition of `mappend` shown in the following doesn't make use of `mapcar;` instead it builds up the list one element at a time:

```lisp
  (defun mappend (fn the-list)
     "Apply fn to each element of list and append the results."
     (if (null the-list)
             nil
             (append (funcall fn (first the-list))
                           (mappend fn (rest the-list)))))
```

`funcall` is similar to `apply;` it too takes a function as its first argument and applies the function to a list of arguments, but in the case of `funcall`, the arguments are listed separately:

```lisp
  > (funcall #'+ 2 3) => 5
  > (apply #' + '(2 3)) => 5
  > (funcall #' + '(2 3)) => *Error: (2 3) is not a number.*
```

These are equivalent to `(+ 2 3), (+ 2 3)`,and`(+ '(2 3))`, respectively.

So far, every function we have used has been either predefined in Common Lisp or introduced with a `defun`, which pairs a function with a name.
It is also possible to introduce a function without giving it a name, using the special syntax `lambda`.

The name *lambda* cornes from the mathematician Alonzo Church's notation for functions (Church 1941).
Lisp usually prefers expressive names over terse Greek letters, but lambda is an exception.
A better name would be `make-function`.
Lambda derives from the notation in Russell and Whitehead's *Principia Mathematica,* which used a caret over bound variables: x^x+x !!!(span) {:.hiddenClass} ![si1_e](images/B9780080571157500017/si1_e.gif).
Church wanted a one-dimensional string, so he moved the caret in front: x^x+x !!!(span) {:.hiddenClass} ![si2_e](images/B9780080571157500017/si2_e.gif).
The caret looked funny with nothing below it, so Church switched to the closest thing, an uppercase lambda, &Lambda;*x*(*x + x*).
The &Lambda; was easily confused with other symbols, so eventually the lowercase lambda was substituted: *&lambda;x*(*x + x*).
John McCarthy was a student of Church's at Princeton, so when McCarthy invented Lisp in 1958, he adopted the lambda notation.
There were no Greek letters on the keypunches of that era, so McCarthy used (`lambda (x) (+ x x)`), and it has survived to this day.
In general, the form of a lambda expression is

```lisp
  (lambda (*parameters...*) *body...*)
```

A lambda expression is just a nonatomic *name* for a function, just as `append` is an atomic name for a built-in function.
As such, it is appropriate for use in the first position of a function call, but if we want to get at the actual function, rather than its name, we still have to use the `#'` notation.
For example:

```lisp
  > ((lambda (x) (+ x 2)) 4) => 6
  *>* (funcall #'(lambda (x) (+ x 2)) 4) => 6
```

To understand the distinction we have to be clear on how expressions are evaluated in Lisp.
The normal rule for evaluation states that symbols are evaluated by looking up the value of the variable that the symbol refers to.
So the `x` in `(+ x 2)` is evaluated by looking up the value of the variable named `x`.
A list is evaluated in one of two ways.
If the first element of the list is a special form opera tor, then the list is evaluated according to the syntax rule for that special form.
Otherwise, the list represents a function call.
The first element is evaluated in a unique way, as a function.
This means it can either be a symbol or a lambda expression.
In either case, the function named by the first element is applied to the values of the remaining elements in the list.
These values are determined by the normal evaluation rules.
If we want to refer to a function in a position other than the first element of a function call, we have to use the `#'` notation.
Otherwise, the expressions will be evaluated by the normal evaluation rule, and will not be treated as functions.
For example:

```lisp
  > append => *Error: APPEND is not a bound variable*
  > (lambda (x) (+ x 2)) => *Error: LAMBDA is not a function*
```

Here are some more examples of the correct use of functions:

```lisp
  >(mapcar #'(lambda (x) (+ x x))
                 '(1 2 3 4 5)) =>
  (2 4 6 8 10)
  > (mappend #'(lambda (l) (list l (reverse l)))
                   ((1 2 3) (a b c))) =>
  ((1 2 3) (3 2 1) (A B C) (C B A))
```

Programmers who are used to other languages sometimes fail to see the point of lambda expressions.
There are two reasons why lambda expressions are very useful.

First, it can be messy to clutter up a program with superfluous names.
Just as it is clearer to write `(a+b)*(c+d)` rather than to invent variable names like `temp1` and `temp2` to hold `a+b` and `c+d`, so it can be clearer to define a function as a lambda expression rather than inventing a name for it.

Second, and more importantly, lambda expressions make it possible to create new functions at run time.
This is a powerful technique that is not possible in most programming languages.
These run-time functions, known as *closures,* will be covered in [section 3.16](B9780080571157500030.xhtml#s0085).

## 1.8 Other Data Types
{:#s0045}
{:.h1hd}

So far we have seen just four kinds of Lisp objects: numbers, symbols, lists, and functions.
Lisp actually defines about 25 different types of objects: vectors, arrays, structures, characters, streams, hash tables, and others.
At this point we will introduce one more, the string.
As you can see in the following, strings, like numbers, evaluate to themselves.
Strings are used mainly for printing out messages, while symbols are used for their relationships to other objects, and to name variables.
The printed representation of a string has a double quote mark `(")` at each end.

```lisp
  > "a string" => "a string"
  > (length "a string") => 8
  > (length "") => 0
```

## 1.9 Summary: The Lisp Evaluation Rule
{:#s0050}
{:.h1hd}

We can now summarize the evaluation rule for Lisp.

*  Every expression is either a *list* or an *atom.*

*  Every list to be evaluated is either a *special form expression* or a *function application*.

*  A *special form expression* is def ined to be a list whose first element is a special form operator.
The expression is evaluated according to the operator's idiosyncratic evaluation rule.
For example, the evaluation rule for setf is to evaluate the second argument according to the normal evaluation rule, set the first argument to that value, and return the value as the result.
The rule for `defun` is to define a new function, and return the name of the function.
The rule for quote is to return the first argument unevaluated.
The notation `'*x*` is actually an abbreviation for the special form expression `(quote *x*)`.
Similarly, the notation `*#*'*f*` is an abbreviation for the special form expression `(function *f*)`.

```lisp
'John = (quote John) => JOHN
(setf p 'John) => JOHN
defun twice (x) (+ x x)) => TWICE
(if (= 2 3) (error) (+ 5 6)) => 11
```

*  A *function application* is evaluated by first evaluating the arguments (the rest of the list) and then finding the function named by the first element of the list and applying it to the list of evaluated arguments.

```lisp
(+ 2 3) => 5
(- (+ 90 9) (+ 50 5 (length '(Pat Kim)))) => 42
```

Note that if `'(Pat Kim)` did not have the quote, it would betreated as a function application of the function `pat` to the value of the variable `kim.`

*  Every atom is either a *symbol* or a *nonsymbol.*

*  A *symbol* evaluates to the most recent value that has been assigned to the variable named by that symbol.
Symbols are composed of letters, and possibly digits and, rarely, punctuation characters.
To avoid confusion, we will use symbols composed mostly of the letters `a-z` and the `'-'` character, with a few exceptions.[6](#fn0035)

```lisp
names
p
*print-pretty*
```

*  A *nonsymbol atom* evaluates to itself.
For now, numbers and strings are the only such non-symbol atoms we know of.
Numbers are composed of digits, and possibly a decimal point and sign.
There are also provisions for scientific notation, rational and complex numbers, and numbers with different bases, but we won't describe the details here.
Strings are delimited by double quote marks on both sides.

```lisp
42 => 42
- 273.15 => -273.15
"a string" => "a string"
```

There are some minor details of Common Lisp that complicate the evaluation rules, but this definition will suffice for now.

One complication that causes confusion for beginning Lispers is the difference between *reading* and *evaluating* an expression.
Beginners often imagine that when they type an expression, such as

```lisp
  > (+ (* 3 4) (* 5 6))
```

the Lisp system first reads the (`+`, then fetches the addition function, then reads `(* 3 4)` and computes `12`, then reads `(* 5 6)` and computes 30, and finally computes 42.
In fact, what actually happens is that the system first reads the entire expression, the list `(+ (* 3 4) (* 5 6))`.
Only after it has been read does the system begin to evaluate it.
This evaluation can be done by an interpreter that looks at the list directly, or it can be done by a compiler that translates the list into machine language instructions and then executes those instructions.

We can see now that it was a little imprecise to say, "Numbers are composed of digits, and possibly a decimal point and sign." It would be more precise to say that the printed representation of a number, as expected by the function read and as produced by the function print, is composed of digits, and possibly a decimal point and sign.
The internal representation of a number varies from one computer to another, but you can be sure that it will be a bit pattern in a particular memory location, and it will no longer contain the original characters used to represent the number in decimal notation.
Similarly, it is the printed representation of a string that is surrounded by double quote marks; the internal representation is a memory location marking the beginning of a vector of characters.

Beginners who fail to grasp the distinction between reading and evaluating may have a good model of what expressions evaluate to, but they usually have a terrible model of the efficiency of evaluating expressions.
One student used only one-letter variable names, because he felt that it would be faster for the computer to look up a one-letter name than a multiletter name.
While it may be true that shorter names can save a microsecond at read time, this makes no difference at all at evaluation time.
Every variable, regardless of its name, is just a memory location, and the time to access the location does not depend on the name of the variable.

## 1.10 What Makes Lisp Different?
{:#s0055}
{:.h1hd}

What is it that sets Lisp apart from other languages?
Why is it a good language for AI applications?
There are at least eight important factors:

*  Built-in Support for Lists

*  Automatic Storage Management

*  Dynamic Typing

*  First-Class Functions

*  Uniform Syntax

*  Interactive Environment

*  Extensibility

*  History

In sum, these factors allow a programmer to delay making decisions.
In the example dealing with names, we were able to use the built-in list functions to construct and manipulate names without making a lot of explicit decisions about their representation.
If we decided to change the representation, it would be easy to go back and alter parts of the program, leaving other parts unchanged.

This ability to delay decisions-or more accurately, to make temporary, nonbinding decisions-is usually a good thing, because it means that irrelevant details can be ignored.
There are also some negative points of delaying decisions.
First, the less we tell the compiler, the greater the chance that it may have to produce inefficient code.
Second, the less we tell the compiler, the less chance it has of noticing inconsistencies and warning us.
Errors may not be detected until the program is run.
Let's consider each factor in more depth, weighing the advantages and disadvantages:

*  *Built-in Support for Lists.* The list is a very versatile data structure, and while lists can be implemented in any language, Lisp makes it easy to use them.
Many AI applications involve lists of constantly changing size, making fixed-length data structures like vectors harder to use.
Early versions of Lisp used lists as their only aggregate data structure.
Common Lisp provides other types as well, because lists are not always the most efficient choice.

*  *Automatic Storage Management.* The Lisp programmer needn't keep track of memory allocation; it is all done automatically.
This frees the programmer of a lot of effort, and makes it easy to use the functional style of programming.
Other languages present programmers with a choice.
Variables can be allocated on the stack, meaning that they are created when a procedure is entered, and disappear when the procedure is done.
This is an efficient use of storage, but it rules out functions that return complex values.
The other choice is for the programmer to explicitly allocate and free storage.
This makes the functional style possible but can lead to errors.

For example, consider the trivial problem of Computing the expression *a*x (b + c), where *a*, *b*, and *c* are numbers.
The code is trivial in any language; here it is in Pascal and in Lisp:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `/* Pascal */` | `;;; Lisp` |
| `a * (b + c)` | `(* a (+ b c))` |

The only difference is that Pascal uses infix notation and Lisp uses prefix.
Now consider Computing *a*x (b + c) when *a*, *b*, and *c* are matrices.
Assume we have procedures for matrix multiplication and addition.
In Lisp the form is exactly the same; only the names of the functions are changed.
In Pascal we have the choice of approaches mentioned before.
We could declare temporary variables to hold intermediate results on the stack, and replace the functional expression with a series of procedure calls:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `/* Pascal */` | `;;; Lisp` |
| `var temp, result: matrix;` | |
| `add(b,c,temp);` | `(mult a (add b c))` |
| `mult(a,temp,result);` | |
| `return(result);` | |

The other choice is to write Pascal functions that allocate new matrices on the heap.
Then one can write nice functional expressions like `mult(a,add(b,c))` even in Pascal.
However, in practice it rarely works this nicely, because of the need to manage storage explicitly:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `/* Pascal */` | `;;; Lisp` |
| `var a,b,c,x,y: matrix;` | |
| `x := add(b.c);` | `(mult a (add b c))` |
| `y := mult(a,x);` | |
| `free(x);` | |
| `return(y);` | |

In general, deciding which structures to free is a difficult task for the Pascal programmer.
If the programmer misses some, then the program may run out of memory.
Worse, if the programmer frees a structure that is still being used, then strange errors can occur when that piece of memory is reallocated.
Lisp automatically allocates and frees structures, so these two types of errors can *never* occur.

*  *Dynamic Typing.* Lisp programmers don't have to provide type declarations, because the language keeps track of the type of each object at run time, rather than figuring out all types at compile time.
This makes Lisp programs shorter and hence faster to develop, and it also means that functions can often be extended to work for objects to which they were not originally intended to apply.
In Pascal, we can write a procedure to sort an array of 100 integers, but we can't use that same procedure to sort 200 integers, or 100 strings.
In Lisp, one `sort` fits all.
One way to appreciate this kind of flexibility is to see how hard it is to achieve in other languages.
It is impossible in Pascal; in fact, the language Modula was invented primarily to fix this problem in Pascal.
The language Ada was designed to allow flexible generic functions, and a book by [Musser and Stepanov (1989)](B9780080571157500285.xhtml#bb0885) describes an Ada package that gives some of the functionality of Common Lisp's sequence functions.
But the Ada solution is less than ideal: it takes a 264-page book to duplicate only part of the functionality of the 20-page chapter 14 from [Steele (1990)](B9780080571157500285.xhtml#bb1160), and Musser and Stepanov went through five Ada compilers before they found one that would correctly compile their package.
Also, their package is considerably less powerful, since it does not handle vectors or optional keyword parameters.
In Common Lisp, all this functionality cornes for free, and it is easy to add more.
On the other hand, dynamic typing means that some errors will go undetected until run time.
The great advantage of strongly typed languages is that they are able to give error messages at compile time.
The great frustration with strongly typed languages is that they are only able to warn about a small class of errors.
They can tell you that you are mistakenly passing a string to a function that expects an integer, but they can't tell you that you are passing an odd number to a function that expects an even number.

*  *First-Class Functions.* A *first-class* object is one that can be used anywhere and can be manipulated in the same ways as any other kind of object.
In Pascal or C, for example, functions can be passed as arguments to other functions, but they are not first-class, because it is not possible to create new functions while the program is running, nor is it possible to create an anonymous function without giving it a name.
In Lisp we can do both those things using `lambda`.
This is explained in [section 3.16](B9780080571157500030.xhtml#s0085), [page 92](B9780080571157500030.xhtml#p92).

*  *Uniform Syntax.* The syntax of Lisp programs is simple.
This makes the language easy to learn, and very little time is wasted correcting typos.
In addition, it is easy to write programs that manipulate other programs or define whole new languages-a very powerful technique.
The simple syntax also makes it easy for text editing programs to parse Lisp.
Your editor program should be able to indent expressions automatically and to show matching parentheses.
This is harder to do for languages with complex syntax.
On the other hand, some people object to all the parentheses.
There are two answers to this objection.
First, consider the alternative: in a language with "conventional" syntax, Lisp's parentheses pairs would be replaced either by an implicit operator precedence rule (in the case of arithmetic and logical expressions) or by a `begin/end` pair (in the case of control structures).
But neither of these is necessarily an advantage.
Implicit precedence is notoriously error-prone, and `begin/end` pairs clutter up the page without adding any content.
Many languages are moving away from `begin/end: C` uses { and }, which are equivalent to parentheses, and several modem functional languages (such as Haskell) use horizontal blank space, with no explicit grouping at all.
Second, many Lisp programmers *have* considered the alternative.
There have been a number of preprocessors that translate from "conventional" syntax into Lisp.
None of these has caught on.
It is not that Lisp programmers find it *tolerable* to use all those parentheses, rather, they find it *advantageous.* With a little experience, you may too.
It is also important that the syntax of Lisp data is the same as the syntax of programs.
Obviously, this makes it easy to convert data to program.
Less obvious is the time saved by having universal functions to handle input and output.
The Lisp functions `read` and `print` will automatically handle any list, structure, string, or number.
This makes it trivial to test individual functions while developing your program.
In a traditional language like C or Pascal, you would have to write special-purpose functions to read and print each data type you wanted to debug, as well as a special-purpose driver to call the routines.
Because this is time-consuming and error-prone, the temptation is to avoid testing altogether.
Thus, Lisp encourages better-tested programs, and makes it easier to develop them faster.

*  *Interactive Environment.* Traditionally, a programmer would write a complete program, compile it, correct any errors detected by the compiler, and then run and debug it.
This is known as the *batch* mode of interaction.
For long programs, waiting for the compiler occupied a large portion of the debugging time.
In Lisp one normally writes a few small functions at a time, getting feedback from the Lisp system after evaluating each one.
This is known as an *interactive* environment.
When it cornes time to make a change, only the changed functions need to be recompiled, so the wait is much shorter.
In addition, the Lisp programmer can debug by typing in arbitrary expressions at any time.
This is a big improvement over editing the program to introduce print statements and recompiling.
Notice that the distinction between *interactive* and a *batch* languages is separate from the distinction between *interpreted* and *compiled* languages.
It has often been stated, incorrectly, that Lisp has an advantage by virtue of being an interpreted language.
Actually, experienced Common Lisp programmers tend to use the compiler almost exclusively.
The important point is interaction, not interpretation.
The idea of an interactive environment is such a good one that even traditional languages like C and Pascal are starting to offer interactive versions, so this is not an exclusive advantage of Lisp.
However, Lisp still provides much better access to the interactive features.
A C interpreter may allow the programmer to type in an expression and have it evaluated immediately, but it will not allow the programmer to write a program that, say, goes through the symbol table and finds all the user-defined functions and prints information on them.
In C-even interpreted C-the symbol table is just a Cheshire-cat-like invention of the interpreter's imagination that disappears when the program is run.
In Lisp, the symbol table is a first-class object[7](#fn0040) that can be accessed and modified with functions like `read, intern` and `do-symbols`.
Common Lisp offers an unusually rich set of useful tools, including over 700 built-in functions (ANSI Common Lisp has over 900).
Thus, writing a new program involves more gathering of existing pieces of code and less writing of new code from scratch.
In addition to the standard functions, Common Lisp implementations usually provide extensions for interacting with the editor, debugger, and window system.

*  *Extensibility*.
When Lisp was invented in 1958, nobody could have foreseen the advances in programming theory and language design that have taken place in the last thirty years.
Other early languages have been discarded, replaced by ones based on newer ideas.
However, Lisp has been able to survive, because it has been able to adapt.
Because Lisp is extensible, it has been changed to incorporate the newest features as they become popular.
The easiest way to extend the language is with macros.
When so-called structured programming constructs such as *case* and *if-then-else* arose, they were incorporated into Lisp as macros.
But the flexibility of Lisp goes beyond adding individual constructs.
Brand new styles of programming can easily be implemented.
Many AI applications are based on the idea of *rule-based* programming.
Another new style is *object-oriented* programming, which has been incorporated with the Common Lisp Object System (CLOS),[8](#fn0045) a set of macros, functions, and data types that have been integrated into ANSI Common Lisp.

To show how far Lisp has come, here's the only sample program given in the *Lisp/MTS Programmer's Guide* ([Hafner and Wilcox 1974](B9780080571157500285.xhtml#bb0505)):

```lisp
  (PROG (LIST DEPTH TEMP RESTLIST)
  (SETQ RESTLIST (LIST (CONS (READ) O)))
  A (COND
  ((NOT RESTLIST) (RETURN 'DONE))
  (T (SETQ LIST (UNCONS (UNCONS RESTLIST
         RESTLIST) DEPTH))
  (COND ((ATOM LIST)
  (MAPC 'PRIN1 (LIST '"ATOM:" LIST '"," 'DEPTH DEPTH))
  (TERPRI))
  (T (SETQ TEMP (UNCONS LIST LIST))
  (COND (LIST
  (SETQ RESTLIST (CONS(CONS LIST DEPTH) RESTLIST))))
  (SETQ RESTLIST (CONS (CONS TEMP
         (ADD1 DEPTH)) RESTLIST))
  ))))
  ))))(GO A))
```

Note the use of the now-deprecated goto `(GO)` statement, and the lack of consistent indexation conventions.
The manual also gives a recursive version of the same program:

```lisp
  (PROG NIL (
  (LABEL ATOMPRINT (LAMBDA (RESTLIST)
  (COND ((NOT RESTLIST) (RETURN 'DONE))
  ((ATOM (CAAR RESTLIST)) (MAPC 'PRIN1
         (LIST '"ATOM:" (CAAR RESTLIST)
               '"," DEPTH (CDAR RESTLIST)))
  (TERPRI)
  (ATOMPRINT (CDR RESTLIST)))
  ( T (ATOMPRINT (GRAFT
  (LIST (CONS (CAAAR RESTLIST) (ADD1 (CDAR RESTLIST))))
  (AND (CDAAR RESTLIST) (LIST (CONS (CDAAR RESTLIST)
          (CDAR RESTLIST))))
                    (CDR RESTLIST)))))))
  (LIST (CONS (READ) 0))))
```

Both versions are very difficult to read.
With our modem insight (and text editors that automatically indent), a much simpler program is possible:

```lisp
  (defun atomprint (exp &optional (depth 0))
     "Print each atom in exp, along with its depth of nesting."
     (if (atom exp)
            (format t "~&ATOM: ~ a, DEPTH ~ d" exp depth)
            (dolist (element exp)
               (atomprint element (+ depth 1)))))
```

## 1.11 Exercises
{:#s1060}
{:.h1hd}

  **Exercise 1.1 [m]** Define a version of `last-name` that handles "Rex Morgan MD," "Morton Downey, Jr.," and whatever other cases you can think of.

  **Exercise 1.2 [m]** Write a function to exponentiate, or raise a number to an integer power.
For example: `(power 3 2) = 32 = 9`.

  **Exercise 1.3 [m]** Write a function that counts the number of atoms in an expression.
For example: `(count-atoms '(a (b) c)) = 3`.
Notice that there is something of an ambiguity in this: should (`a nil c`) count as three atoms, or as two, because it is equivalent to (`a () c`)?

  **Exercise 1.4 [m]** Write a function that counts the number of times an expression occurs anywhere within another expression.
Example: `(count-anywhere 'a '(a ((a) b) a)) => 3.`

  **Exercise 1.5 [m]** Write a function to compute the dot product of two sequences of numbers, represented as lists.
The dot product is computed by multiplying corresponding elements and then adding up the resulting products.
Example:

```lisp
(dot-product '(10 20) '(3 4)) = 10 x 3 + 20 x 4 = 110
```

## 1.12 Answers
{:#s0060}
{:.h1hd}

**Answer 1.2**

```lisp
  (defun power (x n)
     "Power raises x to the nth power. N must be an integer >= 0.
     This executes in log n time, because of the check for even n."
    (cond ((= n 0) 1)
               ((evenp n) (expt (power x (/ n 2)) 2))
               (t (* x (power x (- n 1))))))
```

**Answer 1.3**

```lisp
  (defun count-atoms (exp)
     "Return the total number of non-nil atoms in the expression."
     (cond ((null exp) 0)
               ((atom exp) 1)
               (t (+ (count-atoms (first exp))
                          (count-atoms (rest exp))))))
  (defun count-all-atoms (exp &optional (if-null 1))
     "Return the total number of atoms in the expression,
     counting nil as an atom only in non-tail position."
     (cond ((null exp) if-null)
                ((atom exp) 1)
                (t (+ (count-all-atoms (first exp) 1)
                           (count-all-atoms (rest exp) 0)))))
```

**Answer 1.4**

```lisp
  (defun count-anywhere (item tree)
     "Count the times item appears anywhere within tree."
     (cond ((eql item tree) 1)
                ((atom tree) 0)
                (t (+ (count-anywhere item (first tree))
                           (count-anywhere item (rest tree))))))
```

**Answer 1.5** Here are three versions:

```lisp
  (defun dot-product (a b)
     "Compute the mathematical dot product of two vectors."
     (if (or (null a) (null b))
             0
             (+ (* (first a) (first b))
                  (dot-product (rest a) (rest b)))))
  (defun dot-product (a b)
     "Compute the mathematical dot product of two vectors."
     (let ((sum 0))
         (dotimes (i (length a))
            (incf sum (* (elt a i) (elt b i))))
         sum))
  (defun dot-product (a b)
     "Compute the mathematical dot product of two vectors."
     (apply #'+ (mapcar #'* a b)))
```

----------------------

[1](#xfn0010) This list of symbols is not a legal Lisp assignaient statement, but it is a Lisp data object.
!!!(p) {:.ftnote1}

[2](#xfn0015) The variable `*print-case*` controls how symbols will be printed.
By default, the value of this variable is :`upcase`, but it can be changed to :`downcaseor :capitalize`.
!!!(p) {:.ftnote1}

[3](#xfn0020) Later we will see what happens when the second argument is not a list.
!!!(p) {:.ftnote1}

[4](#xfn0025) In ANSI Common Lisp, `last` is defined to return a list of the last *n* elements, where n defaultstoi.
Thus `(last p) = (last p 1) = (PUBLIC)`,and `(last p 2) = (Q PUBLIC)`.
This may make the definition of last seem less perverse.
!!!(p) {:.ftnote1}

[5](#xfn0030) Just as we can change the value of a variable, we can also change the value of a function in Lisp.
It is not necessary to recompile everything when a change is made, as it would be in other languages.
!!!(p) {:.ftnote1}

[6](#xfn0035) For example, symbols that denote so-called *special* variables usually begin and end in asterisks.
Also, note that I did not hesitate to use the symbol `won !` on page 11.
!!!(p) {:.ftnote1}

[7](#xfn0040) Actually, there can be several symbol tables.
They are known as *packages* in Common Lisp.
!!!(p) {:.ftnote1}

[8](#xfn0045) Pronounced "see-loss." An alternate pronunciation, "klaus," seems to be losing favor.
!!!(p) {:.ftnote1}

# Chapter 2
## A Simple Lisp Program
{:.chaptitle}

> *Certum quod factum.*

> (One is certain of only what one builds.)

> - Giovanni Battista Vico (1668-1744)

> Italian royal historiographer

You will never become proficient in a foreign language by studying vocabulary lists.
Rather, you must hear and speak (or read and write) the language to gain proficiency.
The same is true for learning computer languages.

This chapter shows how to combine the basic functions and special forms of Lisp into a complete program.
If you can learn how to do that, then acquiring the remaining vocabulary of Lisp (as outlined in [chapter 3](B9780080571157500030.xhtml)) will be easy.

## 2.1 A Grammar for a Subset of English
{:#s0010}
{:.h1hd}

The program we will develop in this chapter generates random English sentences.
Here is a simple grammar for a tiny portion of English:

  *Sentence*=> *Noun-Phrase + Verb-Phrase*

  *Noun-Phrase*=> *Article + Noun*

  *Verb-Phrase*=> *Verb + Noun-Phrase*

  *Article*=> *the, a,...*

  *Noun*=> *man, ball, woman, table...*

  *Verb*=> *hit, took, saw, liked...*

To be technical, this description is called a *context-free phrase-structure grammar*, and the underlying paradigm is called *generative syntax*.
The idea is that anywhere we want a sentence, we can generate a noun phrase followed by a verb phrase.
Anywhere a noun phrase has been specified, we generate instead an article followed by a noun.
Anywhere an article has been specified, we generate either "the," "a," or some other article.
The formalism is "context-free" because the rules apply anywhere regardless of the surrounding words, and the approach is "generative" because the rules as a whole define the complete set of sentences in a language (and by contrast the set of nonsentences as well).
In the following we show the derivation of a single sentence using the rules:

  To get a *Sentence*, append a *Noun-Phrase* and a *Verb-Phrase*

     To get a *Noun-Phrase*, append an *Article* and a *Noun*

          Choose "*the*" for the *Article*

          Choose "*man*" for the *Noun*

     The resulting *Noun-Phrase* is "*the man*"

     To get a *Verb-Phrase*, append a *Verb* and a *Noun-Phrase*

          Choose "*hit*" for the *Verb*

        To get a *Noun-Phrase*, append an *Article* and a *Noun*

          Choose "*the*" for the *Article*

          Choose "*ball*" for the *Noun*

       The resulting *Noun-Phrase* is "*the ball*"

     The resulting *Verb-Phrase* is "*hit the ball*"

  The resulting *Sentence* is "*The man hit the ball*"

## 2.2 A Straightforward Solution
{:#s0015}
{:.h1hd}

We will develop a program that generates random sentences from a phrase-structure grammar.
The most straightforward approach is to represent each grammar rule by a separate Lisp function:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `(defun sentence ()` | `(append (noun-phrase) (verb-phrase)))` |
| `(defun noun-phrase ()` | `(append (Article) (Noun)))` |
| `(defun verb-phrase ()` | `(append (Verb) (noun-phrase)))` |
| `(defun Article ()` | `(one-of '(the a)))` |
| `(defun Noun ()` | `(one-of '(man ball woman table)))` |
| `(defun Verb ()` | `(one-of '(hit took saw liked)))` |

Each of these function definitions has an empty parameter list, `()`.
That means the functions take no arguments.
This is unusual because, strictly speaking, a function with no arguments would always return the same thing, so we would use a constant instead.
However, these functions make use of the `random` function (as we will see shortly), and thus can return different results even with no arguments.
Thus, they are not functions in the mathematical sense, but they are still called functions in Lisp, because they return a value.

All that remains now is to define the function `one-of`.
It takes a list of possible choices as an argument, chooses one of these at random, and returns a one-element list of the element chosen.
This last part is so that all functions in the grammar will return a list of words.
That way, we can freely apply `append` to any category.

```lisp
  (defun one-of (set)
     "Pick one element of set, and make a list of it."
     (list (random-elt set)))
  (defun random-elt (choices)
     "Choose an element from a list at random."
     (elt choices (random (length choices))))
```

There are two new functions here, `elt` and `random.``elt` picks an element out of a list.
The first argument is the list, and the second is the position in the list.
The confusing part is that the positions start at 0, so `(elt choices 0)` is the first element of the list, and `(elt choices 1)` is the second.
Think of the position numbers as telling you how far away you are from the front.
The expression `(random n)` returns an integer from 0 to n-1, so that `(random 4)` would return either 0,1,2, or 3.

Now we can test the program by generating a few random sentences, along with a noun phrase and a verb phrase:

```lisp
  > (sentence)`=> `(THE WOMAN HIT THE BALL)
  > (sentence)`=> `(THE WOMAN HIT THE MAN)
  > (sentence)`=> `(THE BALL SAW THE WOMAN)
  > (sentence)`=> `(THE BALL SAW THE TABLE)
  > (noun-phrase)`=> `(THE MAN)
  > (verb-phrase)`=> `(LIKED THE WOMAN)
  > (trace sentence noun-phrase verb-phrase article noun verb) =>` `(SENTENCE NOUN-PHRASE VERB-PHRASE ARTICLE NOUN VERB)
```

  `> (sentence)`=>

```lisp
 (1 ENTER SENTENCE)
   (1 ENTER NOUN-PHRASE)
     (1 ENTER ARTICLE)
     (1 EXIT ARTICLE: (THE))
     (1 ENTER NOUN)
     (1 EXIT NOUN: (MAN))
   (1 EXIT NOUN-PHRASE: (THE MAN))
   (1 ENTER VERB-PHRASE)
      (1 ENTER VERB)
      (1 EXIT VERB: (HIT))
      (1 ENTER NOUN-PHRASE)
        (1 ENTER ARTICLE)
        (1 EXIT ARTICLE: (THE))
        (1 ENTER NOUN)
        (1 EXIT NOUN: (BALL))
      (1 EXIT NOUN-PHRASE: (THE BALL))
    (1 EXIT VERB-PHRASE: (HIT THE BALL))
  (1 EXIT SENTENCE: (THE MAN HIT THE BALL))
  (THE MAN HIT THE BALL)
```

The program works fine, and the trace looks just like the sample derivation above, but the Lisp definitions are a bit harder to read than the original grammar rules.
This problem will be compounded as we consider more complex rules.
Suppose we wanted to allow noun phrases to be modified by an indefinite number of adjectives and an indefinite number of prepositional phrases.
In grammatical notation, we might have the following rules:

  *Noun-Phrase*=> *Article + Adj* + Noun + PP**

  *Adj**=> *!!!(char) Ø, Adj + Adj**

  *PP**=> *!!!(char) Ø, PP + PP**

  *PP*=> *Prep + Noun-Phrase*

  *Adj*=> *big, little, blue, green*,...

  *Prep*=> *to, in, by, with*,...

In this notation, !!!(char) Ø indicates a choice of nothing at all, a comma indicates a choice of several alternatives, and the asterisk is nothing special-as in Lisp, it's just part of the name of a symbol.
However, the convention used here is that names ending in an asterisk denote zero or more repetitions of the underlying name.
That is, *PP** denotes zero or more repetitions of *PP*.
This is known as "Kleene star" notation (pronounced "clean-E") after the mathematician Stephen Cole Kleene.[1](#fn0010)

The problem is that the rules for *Adj** and *PP** contain choices that we would have to represent as some kind of conditional in Lisp.
For example:

```lisp
  (defun Adj* ()
     (if (= (random 2) 0)
             nil
             (append (Adj) (Adj*))))
  (defun PP* ()
     (if (random-elt '(t nil))
             (append (PP) (PP*))
             nil))
  (defun noun-phrase () (append (Article) (Adj*) (Noun) (PP*)))
  (defun PP () (append (Prep) (noun-phrase)))
  (defun Adj () (one-of '(big little blue green adiabatic)))
  (defun Prep () (one-of '(to in by with on)))
```

I've chosen two different implementations for `Adj*` and `PP*`; either approach would work in either function.
We have to be careful, though; here are two approaches that would not work:

```lisp
  (defun Adj* ()
     "Warning - incorrect definition of Adjectives."
     (one-of '(nil (append (Adj) (Adj*)))))
  (defun Adj* ()
     "Warning - incorrect definition of Adjectives."
     (one-of (list nil (append (Adj) (Adj*)))))
```

The first definition is wrong because it could return the literal expression `((append (Adj) (Adj*)))` rather than a list of words as expected.
The second definition would cause infinite recursion, because Computing the value of `(Adj*)` always involves a recursive call to `(Adj*)`.
The point is that what started out as simple functions are now becoming quite complex.
To understand them, we need to know many Lisp conventions-`defun, (), case, if`, `quote`, and the rules for order of evaluation-when ideally the implementation of a grammar rule should use only *linguistic* conventions.
If we wanted to develop a larger grammar, the problem could get worse, because the rule-writer might have to depend more and more on Lisp.

## 2.3 A Rule-Based Solution
{:#s0020}
{:.h1hd}

An alternative implementation of this program would concentrate on making it easy to write grammar rules and would worry later about how they will be processed.
Let's look again at the original grammar rules:

  *Sentence*=> *Noun-Phrase + Verb-Phrase*

  *Noun-Phrase*=> *Article + Noun*

  *Verb-Phrase*=> *Verb + Noun-Phrase*

  *Article*=> *the, a,...*

  *Noun*=> *man, ball, woman, table ...*

  *Verb*=> *hit, took, saw, liked...*

Each rule consists of an arrow with a symbol on the left-hand side and something on the right-hand side.
The complication is that there can be two kinds of right-hand sides: a concatenated list of symbols, as in "*Noun-Phrase => Article+Noun*," or a list of alternate words, as in "*Noun => man, ball,...*" We can account for these possibilities by deciding that every rule will have a list of possibilities on the right-hand side, and that a concatenated list, *for example "Article+Noun,"* will be represented as a Lisp list, *for example*"(`Article Noun`)".
The list of rules can then be represented as follows:

```lisp
  (defparameter *simple-grammar*
     '((sentence -> (noun-phrase verb-phrase))
       (noun-phrase -> (Article Noun))
       (verb-phrase -> (Verb noun-phrase))
       (Article -> the a)
       (Noun -> man ball woman table)
       (Verb -> hit took saw liked))
     "A grammar for a trivial subset of English.")
  (defvar *grammar* *simple-grammar*
     "The grammar used by generate. Initially, this is
     *simple-grammar*, but we can switch to other grammars.")
```

Note that the Lisp version of the rules closely mimics the original version.
In particular, I include the symbol "->", even though it serves no real purpose; it is purely decorative.

The special forms `defvar` and `defparameter` both introduce special variables and assign a value to them; the difference is that a *variable*, like `*grammar*,` is routinely changed during the course of running the program.
A *parameter*, like `*simple-grammar*`, on the other hand, will normally stay constant.
A change to a parameter is considered a change *to* the program, not a change *by* the program.

Once the list of rules has been defined, it can be used to find the possible rewrites of a given category symbol.
The function `assoc` is designed for just this sort of task.
It takes two arguments, a "key" and a list of lists, and returns the first element of the list of lists that starts with the key.
If there is none, it returns `nil`.
Here is an example:

```lisp
  > (assoc 'noun *grammar*)`=> `(NOUN -> MAN BALL WOMAN TABLE)
```

Although rules are quite simply implemented as lists, it is a good idea to impose a layer of abstraction by defining functions to operate on the rules.
We will need three functions: one to get the right-hand side of a rule, one for the left-hand side, and one to look up all the possible rewrites (right-hand sides) for a category.

```lisp
  (defun rule-lhs (rule)
     "The left-hand side of a rule."
     (first rule))
  (defun rule-rhs (rule)
     "The right-hand side of a rule."
     (rest (rest rule)))
  (defun rewrites (category)
     "Return a list of the possible rewrites for this category."
     (rule-rhs (assoc category *grammar*)))
```

Defining these functions will make it easier to read the programs that use them, and it also makes changing the representation of rules easier, should we ever decide to do so.

We are now ready to address the main problem: defining a function that will generate sentences (or noun phrases, or any other category).
We will call this function `generate.` It will have to contend with three cases: (1) In the simplest case, `generate` is passed a symbol that has a set of rewrite rules associated with it.
We choose one of those at random, and then generate from that.
(2) If the symbol has no possible rewrite rules, it must be a terminal symbol-a word, rather than a grammatical category-and we want to leave it alone.
Actually, we return the list of the input word, because, as in the previous program, we want all results to be lists of words.
(3) In some cases, when the symbol has rewrites, we will pick one that is a list of symbols, and try to generate from that.
Thus, `generate` must also accept a list as input, in which case it should generate each element of the list, and then append them all together.
In the following, the first clause in `generate` handles this case, while the second clause handles (1) and the third handles (2).
Note that we used the `mappend` function from [section 1.7](B9780080571157500017.xhtml#s0040) ([page 18](B9780080571157500017.xhtml#p18)).

```lisp
  (defun generate (phrase)
     "Generate a random sentence or phrase"
     (cond ((listp phrase)
                 (mappend #'generate phrase))
                 ((rewrites phrase)
                  (generate (random-elt (rewrites phrase))))
                 (t (list phrase))))
```

Like many of the programs in this book, this function is short, but dense with information: the craft of programming includes knowing what *not* to write, as well as what to write.

This style of programming is called *data-driven* programming, because the data (the list of rewrites associated with a category) drives what the program does next.
It is a natural and easy-to-use style in Lisp, leading to concise and extensible programs, because it is always possible to add a new piece of data with a new association without having to modify the original program.

Here are some examples of generate in use:

```lisp
  > (generate 'sentence)`=> `(THE TABLE SAW THE BALL)
  > (generate 'sentence)`=> `(THE WOMAN HIT A TABLE)
  > (generate 'noun-phrase)`=> `(THE MAN)
  > (generate 'verb-phrase)`=> `(TOOK A TABLE)
```

There are many possible ways to write `generate`.
The following version uses `if` instead of `cond`:

```lisp
  (defun generate (phrase)
     "Generate a random sentence or phrase"
     (if (listp phrase)
             (mappend #'generate phrase)
             (let ((choices (rewrites phrase)))
               (if (null choices)
                       (list phrase)
                       (generate (random-elt choices))))))
```

This version uses the special form `let`, which introduces a new variable (in this case, `choices`) and also binds the variable to a value.
In this case, introducing the variable saves us from calling the function `rewrites twice`, as was done in the `cond` version of `generate`.
The general form of a `let` form is:

  `(let` ((*var value*)...)

    * body-containing-vars*)

`let` is the most common way of introducing variables that are not parameters of functions.
One must resist the temptation to use a variable without introducing it:

```lisp
  (defun generate (phrase)
   (setf choices ...) ;; wrong!
   ... choices ...)
```

This is wrong because the symbol `choices` now refers to a special or global variable, one that may be shared or changed by other functions.
Thus, the function generate is not reliable, because there is no guarantee that `choices` will retain the same value from the time it is set to the time it is referenced again.
With `let` we introduce a brand new variable that nobody else can access; therefore it is guaranteed to maintain the proper value.

**Exercise 2.1 [m]** Write a version of `generate` that uses `cond` but avoids calling `rewrites twice`.

**Exercise 2.2 [m]** Write a version of `generate` that explicitly differentiates between terminal symbols (those with no rewrite rules) and nonterminal symbols.

## 2.4 Two Paths to Follow
{:#s0025}
{:.h1hd}

The two versions of the preceding program represent two alternate approaches that come up time and time again in developing programs: (1) Use the most straightforward mapping of the problem description directly into Lisp code.
(2) Use the most natural notation available to solve the problem, and then worry about writing an interpreter for that notation.

Approach (2) involves an extra step, and thus is more work for small problems.
However, programs that use this approach are often easier to modify and expand.
This is especially true in a domain where there is a lot of data to account for.
The grammar of natural language is one such domain-in fact, most AI problems fit this description.
The idea behind approach (2) is to work with the problem as much as possible in its own terms, and to minimize the part of the solution that is written directly in Lisp.

Fortunately, it is very easy in Lisp to design new notations-in effect, new programming languages.
Thus, Lisp encourages the construction of more robust programs.
Throughout this book, we will be aware of the two approaches.
The reader may notice that in most cases, we choose the second.

## 2.5 Changing the Grammar without Changing the Program
{:#s0030}
{:.h1hd}

We show the utility of approach (2) by defining a new grammar that includes adjectives, prepositional phrases, proper names, and pronouns.
We can then apply the `generate` function without modification to this new grammar.

```lisp
  (defparameter *bigger-grammar*
     '((sentence -> (noun-phrase verb-phrase))
         (noun-phrase -> (Article Adj* Noun PP*) (Name) (Pronoun))
         (verb-phrase -> (Verb noun-phrase PP*))
         (PP* -> () (PP PP*))
         (Adj* -> () (Adj Adj*))
         (PP -> (Prep noun-phrase))
         (Prep -> to in by with on)
         (Adj -> big little blue green adiabatic)
         (Article -> the a)
         (Name -> Pat Kim Lee Terry Robin)
         (Noun -> man ball woman table)
         (Verb -> hit took saw liked)
         (Pronoun -> he she it these those that)))
  (setf *grammar* *bigger-grammar*)
  > (generate 'sentence)
  (A TABLE ON A TABLE IN THE BLUE ADIABATIC MAN SAW ROBIN
  WITH A LITTLE WOMAN)
  > (generate 'sentence)
  (TERRY SAW A ADIABATIC TABLE ON THE GREEN BALL BY THAT WITH KIM IN THESE BY A GREEN WOMAN BY A LITTLE ADIABATIC TABLE IN ROBIN ON LEE)
  > (generate 'sentence)
  (THE GREEN TABLE HIT IT WITH HE)
```

Notice the problem with case agreement for pronouns: the program generated "with he," although "with him" is the proper grammatical form.
Also, it is clear that the program does not distinguish sensible from silly output.

## 2.6 Using the Same Data for Several Programs
{:#s0035}
{:.h1hd}

Another advantage of representing information in a declarative form-as rules or facts rather than as Lisp functions-is that it can be easier to use the information for multiple purposes.
Suppose we wanted a function that would generate not just the list of words in a sentence but a representation of the complete syntax of a sentence.
For example, instead of the list `(a woman took a ball)`, we want to get the nested list:

```lisp
  (SENTENCE (NOUN-PHRASE (ARTICLE A) (NOUN WOMAN))
                     (VERB-PHRASE (VERB TOOK)
                                               (NOUN-PHRASE (ARTICLE A) (NOUN BALL))))
```

This corresponds to the tree that linguists draw as in [figure 2.1](#f0010).

![f02-01-9780080571157](images/B9780080571157500029/f02-01-9780080571157.jpg)     
Figure 2.1:
!!!(span) {:.fignum}
Sentence Parse Tree
Using the "straightforward functions" approach we would be stuck; we'd have to rewrite every function to generate the additional structure.
With the "new notation" approach we could keep the grammar as it is and just write one new function: a version of `generate` that produces nested lists.
The two changes are to `cons` the category onto the front of each rewrite, and then not to `append` together the results but rather just list them with `mapcar`:

```lisp
  (defun generate-tree (phrase)
     "Generate a random sentence or phrase,
     with a complete parse tree."
     (cond ((listp phrase)
                  (mapcar #'generate-tree phrase))
                 ((rewrites phrase)
                  (cons phrase
                             (generate-tree (random-elt (rewrites phrase)))))
                 (t (list phrase))))
```

Here are some examples:

```lisp
  > (generate-tree 'Sentence)
  (SENTENCE (NOUN-PHRASE (ARTICLE A)
                                               (ADJ*)
                                               (NOUN WOMAN)
                                               (PP*))
       (VERB-PHRASE (VERB HIT)
                                               (NOUN-PHRASE (PRONOUN HE))
                                               (PP*)))
  > (generate-tree 'Sentence)
  (SENTENCE (NOUN-PHRASE (ARTICLE A)
                                               (NOUN WOMAN))
                    (VERB-PHRASE (VERB TOOK)
                                               (NOUN-PHRASE (ARTICLE A) (NOUN BALL))))
```

As another example of the one-data/multiple-program approach, we can develop a function to generate all possible rewrites of a phrase.
The function `generate-all` returns a list of phrases rather than just one, and we define an auxiliary function, `combine-all`, to manage the combination of results.
Also, there are four cases instead of three, because we have to check for nil explicitly.
Still, the complete program is quite simple:

```lisp
  (defun generate-all (phrase)
     "Generate a list of all possible expansions of this phrase."
     (cond ((null phrase) (list nil))
                 ((listp phrase)
                  (combine-all (generate-all (first phrase))
                                            (generate-all (rest phrase))))
                 ((rewrites phrase)
                  (mappend #'generate-all (rewrites phrase)))
                 (t (list (list phrase)))))
  (defun combine-all (xlist ylist)
     "Return a list of lists formed by appending a y to an x.
     E.g., (combine-all '((a) (b)) '((1) (2)))
      -> ((A 1) (B 1) (A 2) (B 2))."
     (mappend #'(lambda (y)
                             (mapcar #'(lambda (x) (append x y)) xlist))
                       ylist))
```

We can now use `generate-all` to test our original little grammar.
Note that a serious drawback of `generate-all` is that it can't deal with recursive grammar rules like 'Adj* => Adj + Adj*' that appear in `*bigger-grammar*,` since these lead to an infinite number of outputs.
But it works fine for finite languages, like the language generated by *si`mple-grammar*:`

```lisp
  > (generate-all 'Article)
  ((THE) (A))
  > (generate-all 'Noun)
  ((MAN) (BALL) (WOMAN) (TABLE))
  > (generate-all 'noun-phrase)
  ((A MAN) (A BALL) (A WOMAN) (A TABLE)
  (THE MAN) (THE BALL) (THE WOMAN) (THE TABLE))
  > (length (generate-all 'sentence))
  256
```

There are 256 sentences because every sentence in this language has the form Article- Noun-Verb-Article-Noun, and there are two articles, four nouns and four verbs (2 x 4 x 4 x 2 x 4 = 256).

## 2.7 Exercises
{:#s0040}
{:.h1hd}

**Exercise 2.3 [h]** Write a trivial grammar for some other language.
This can be a natural language other than English, or perhaps a subset of a computer language.

**Exercise 2.4 [m]** One way of describing `combine-all` is that it calculates the cross-product of the function `append` on the argument lists.
Write the higher-order function `cross-product`, and define `combine-all` in terms of it.

The moral is to make your code as general as possible, because you never know what you may want to do with it next.

## 2.8 Answers
{:#s0045}
{:.h1hd}

**Answer 2.1**

```lisp
  (defun generate (phrase)
     "Generate a random sentence or phrase"
     (let ((choices nil))
       (cond ((listp phrase)
                    (mappend #'generate phrase))
                   ((setf choices (rewrites phrase))
                    (generate (random-elt choices)))
                   (t (list phrase)))))
```

**Answer 2.2**

```lisp
  (defun generate (phrase)
     "Generate a random sentence or phrase"
     (cond ((listp phrase)
                    (mappend #'generate phrase))
                   ((non-terminal-p phrase)
                     (generate (random-elt (rewrites phrase))))
                   (t (list phrase))))
  (defun non-terminal-p (category)
     "True if this is a category in the grammar."
     (not (null (rewrites category))))
```

**Answer 2.4**

```lisp
  (defun cross-product (fn xlist ylist)
     "Return a list of all (fn x y) values."
     (mappend #'(lambda (y)
                               (mapcar #'(lambda (x) (funcall fn x y))
                                       xlist))
                     ylist))
  (defun combine-all (xlist ylist)
     "Return a list of lists formed by appending a y to an x"
     (cross-product #'append xlist ylist))
```

Now we can use the `cross-product` in other ways as well:

```lisp
  > (cross-product #'+ '(1 2 3) '(10 20 30))
  (11 12 13
   21 22 23
   31 32 33)
  > (cross-product #'list '(a b c d e f g h)
                          '(1 2 3 4 5 6 7 8))
  ((A 1) (B 1) (C 1) (D 1) (E 1) (F 1) (G 1) (H 1)
   (A 2) (B 2) (C 2) (D 2) (E 2) (F 2) (G 2) (H 2)
   (A 3) (B 3) (C 3) (D 3) (E 3) (F 3) (G 3) (H 3)
   (A 4) (B 4) (C 4) (D 4) (E 4) (F 4) (G 4) (H 4)
   (A 5) (B 5) (C 5) (D 5) (E 5) (F 5) (G 5) (H 5)
   (A 6) (B 6) (C 6) (D 6) (E 6) (F 6) (G 6) (H 6)
   (A 7) (B 7) (C 7) (D 7) (E 7) (F 7) (G 7) (H 7)
   (A 8) (B 8) (C 8) (D 8) (E 8) (F 8) (G 8) (H 8))
```

----------------------

[1](#xfn0010) We will soon see "Kleene plus" notation, wherein *PP+* denotes one or more repetition of *PP*.
!!!(p) {:.ftnote1}

# Chapter 3
## Overview of Lisp
{:.chaptitle}

> No doubt about it.
Common Lisp is a *big* language.

> -Guy L.
Steele, Jr.

> Foreword to Koschman 1990

This chapter briefly covers the most important special forms and functions in Lisp.
It can be safely skipped or skimmed by the experienced Common Lisp programmer but is required reading for the novice Lisp programmer, or one who is new to the Common Lisp dialect.

This chapter can be used as a reference source, but the definitive reference is Steele's *Common Lisp the Language*, 2d edition, which should be consulted whenever there is any confusion.
Since that book is 25 times longer than this chapter, it is clear that we can only touch on the important highlights here.
More detailed coverage is given later in this book as each feature is used in a real program.

## 3.1 A Guide to Lisp Style
{:#s0010}
{:.h1hd}

The beginning Common Lisp programmer is often overwhelmed by the number of options that the language provides.
In this chapter we show fourteen different way s to find the length of a list.
How is the programmer to choose between them?
One answer is by reading examples of good programs-as illustrated in this book-and copying that style.
In general, there are six maxims that every programmer should follow:

*  Be specific.

*  Use abstractions.

*  Be concise.

*  Use the provided tools.

*  Don't be obscure.

*  Be consistent.

These require some explanation.

Using the most specific form possible makes it easier for your reader to understand your intent.
For example, the conditional special form `when` is more specific than `if`.
The reader who sees a `when` knows to look for only one thing: the clause to consider when the test is true.
The reader who sees an `if` can rightfully expect two clauses: one for when the test is true, and one for when it is false.
Even though it is possible to use `if` when there is only one clause, it is preferable to use `when,` because `when` is more specific.

One important way of being specific is using abstractions.
Lisp provides very general data structures, such as lists and arrays.
These can be used to implement specific data structures that your program will use, but you should not make the mistake of invoking primitive functions directly.
If you define a list of names:

```lisp
(defvar *names* '((Robert E. Lee) ...))
```

then you should also define functions to get at the components of each name.
To get at `Lee`,use `(last-name (first *names*)),not (caddar *names*)`.

Often the maxims are in concord.
For example, if your code is trying to find an element in a list, you should use `find` (or maybe `find- if`), not `loop` or `do.
find` is more specific than the general constructs `loop` or `do,` it is an abstraction, it is more concise, it is a built-in tool, and it is simple to understand.

Sometimes, however, the maxims are in conflict, and experience will tell you which one to prefer.
Consider the following two ways of placing a new key/value pair on an association list:[1](#fn0010)

```lisp
(push (cons key val) a-list)
(setf a-list (acons key val a-list))
```

The first is more concise.
But the second is more specific, as it uses the `acons` function, which is designed specifically for association lists.
The decision between them probably hinges on obscurity: those who find `acons` to be a familiar function would prefer the second, and those who find it obscure would prefer the first.

A similar choice arises in the question of setting a variable to a value.
Some prefer (`setq x val`) because it is most specific; others use (`setq x val`), feeling that it is more consistent to use a single form, `setf`, for all updating.
Whichever choice you make on such issues, remember the sixth maxim: be consistent.

## 3.2 Special Forms
{:#s0015}
{:.h1hd}

As noted in [chapter 1](B9780080571157500017.xhtml), "special form" is the term used to refer both to Common Lisp's syntactic constructs and the reserved words that mark these constructs.
The most commonly used special forms are:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| definitions | conditional | variables | iteration | other |
| `defun` | `and` | `let` | `do` | `declare` |
| `defstruct` | `case` | `let*` | `do*` | `function` |
| `defvar` | `cond` | `pop` | `dolist` | `progn` |
| `defparameter` | `if` | `push` | `dotimes` | `quote` |
| `defconstant` | `or` | `setf` | `loop` | `return` |
| `defmacro` | `unless` | `incf` | | `trace` |
| `labels` | `when` | `decf` | | `untrace` |

![t0010](images/B9780080571157500030/t0010.png)

To be precise, only `declare, function, if, labels, let, let*, progn` and `quote` are true special forms.
The others are actually defined as macros that expand into calls to more primitive special forms and functions.
There is no real difference to the programmer, and Common Lisp implementations are free to implement macros as special forms and vice versa, so for simplicity we will continue to use "special form" as a blanket term for both true special forms and built-in macros.

### Special Forms for Definitions
{:#s0020}
{:.h2hd}

In this section we survey the special forms that can be used to introduce new global functions, macros, variables, and structures.
We have already seen the `defun` form for defining functions; the `defmacro` form is similar and is covered on [page 66](#p66).

`(defun`*function-name* (*parameter...*) *"optional documentation" body...*)

`(defmacro`*macro-name* (*parameter...*) *"optional documentation" body...*)

There are three forms for introducing special variables.
`defvar` defines a special variable and can optionally be used to supply an initial value and a documentation string.
The initial value is evaluated and assigned only if the variable does not yet have any value, `defparameter` is similar, except that the value is required, and it will be used to change any existing value, `defconstant` is used to declare that a symbol will always stand for a particular value.

`(defvar`*variable-name initial-value "optional documentation"* )

`(defparameter`*variable-name value "optional documentation"*)

`(defconstant`*variable-name value "optional documentation"*)

All the `def` - forms define global objects.
It is also possible to define local variables with `let`, and to define local functions with `labels`, as we shall see.

Most programming languages provide a way to group related data together into a structure.
Common Lisp is no exception.
The `defstruct` special form defines a structure type (known as a *record* type in Pascal) and automatically defines functions to get at components of the structure.
The general syntax is:

`(defstruct`*structure-name "optional documentation" slot...*)

As an example, we could define a structure for names:

```lisp
(defstruct name
  first
  (middle nil)
  last)
```

This automatically defines the constructor function `make-name,` the recognizer predicate `name-p,` and the accessor functions `name-first, name-middle` and `name-last.` The `(middle nil)` means that each new name built by `make-name` will have a middle name of `nil` by default.
Here we create, access, and modify a structure:

`> (setf b (make-name :first 'Barney :last 'Rubble))`=>

```lisp
#S(NAME : FIRST BARNEY :LAST RUBBLE)
> (name-first b)` => `BARNEY
> (name-middle b)` => `NIL
> (name-last b)` => `RUBBLE
> (name-p b)` => `T
> (name-p 'Barney)  =>  NIL   ; *only the results of make-name are names*
> (setf (name-middle b) 'Q)` => `Q
> b  =>  #S(NAME : FIRST BARNEY : MIDDLE Q :LAST RUBBLE)
```

The printed representation of a structure starts with a #S and is followed by a list consisting of the type of the structure and alternating pairs of slot names and values.
Do not let this representation fool you: it is a convenient way of printing the structure, but it is not an accurate picture of the way structures are represented internally.
Structures are actually implemented much like vectors.
For the `name` structure, the type would be in the zero element of the vector, the first name in the first element, middle in the second, and last in the third.
This means structures are more efficient than lists: they take up less space, and any element can be accessed in a single step.
In a list, it takes *n* steps to access the *n*th element.

There are options that give more control over the structure itself and the individual slots.
They will be covered later as they come up.

### Special Forms for Conditionals
{:#s0025}
{:.h2hd}

We have seen the special form `if,` which has the form (`if`*test then-part else-part*), where either the *then-part* or the *else-part* is the value, depending on the success of the *test.* Remember that only `nil` counts as false; all other values are considered true for the purpose of conditionals.
However, the constant `t` is the conventional value used to denote truth (unless there is a good reason for using some other value).

There are actually quite a few special forms for doing conditional evaluation.
Technically, `if` is defined as a special form, while the other conditionals are macros, so in some sense `if` is supposed to be the most basic.
Some programmers prefer to use `if` for most of their conditionals; others prefer `cond` because it has been around the longest and is versatile (if not particularly pretty).
Finally, some programmers opt for a style more like English prose, and freely use `when, unless, if,` and all the others.

The following table shows how each conditional can be expressed in terms of `if` and `cond`.
Actually, these translations are not quite right, because `or, case`, and `cond` take care not to evaluate any expression more than once, while the translations with `if` can lead to multiple evaluation of some expressions.
The table also has translations to `cond.` The syntax of `cond` is a series of *cond-clauses,* each consisting of a test expression followed by any number of *result* expressions:

```lisp
(cond (*test result...*)
      (*test result...*)
      *...*)
```

`cond` goes through the cond-clauses one at a time, evaluating each test expression.
As soon as a test expression evaluates non-nil, the result expressions for that clause are each evaluated, and the last expression in the clause is the value of the whole `cond.` In particular, if a cond-clause consists of just a test and no result expressions, then the value of the `cond` is the test expression itself, if it is non-nil.
If all of the test expressions evaluate to nil, then nil is returned as the value of the `cond.` A common idiom is to make the last cond-clause be ( t *result...*).

The forms `when` and `unless` operate like a single `cond` clause.
Both forms consist of a test followed by any number of consequents, which are evaluated if the test is satisfied-that is, if the test is true for `when` or false for `unless.`

The `and` form tests whether every one of a list of conditions is true, and `or` tests whether any one is true.
Both evaluate the arguments left to right, and stop as soon as the final result can be determined.
Here is a table of equivalences:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| **conditional** | `if`**form** | `cond`**form** |
| `(when`*test abc*) | `(if`*test*`(progn`*a bc*)) | `(cond` (*test a b c*)) |
| `(unless`*test x y*) | `(if (not *test*) (progn`*xy*)) | `(cond ((not`*test*) *x y*)) |
| `(and`*abc*) | `(if`*a*`(if`*b c*)) | `(cond` (*a*`(cond` (*bc*)))) |
| `(or`*abc*) | `(if`*a a*`(if`*b b c*)) | `(cond (a)` (*b*) (*c*)) |
| `(*case*`*a* (*b c*) `*(t x*))` | `(if (eql`*a *b*) *c x*) | `(cond ((eql`*a *b*)*c*) (*tx*)) |

It is considered poor style to use `and` and `or` for anything other than testing a logical condition, `when, unless,` and `if` can all be used for taking conditional action.
For example:

```lisp
(and (> n 100)
    (princ "N is large."))    ; Bad style!
(or (<= n 100)
    (princ "N is large."))    ; Even worse style!
(cond ((> n 100)        ; OK, but not MY preference
      (princ "N is large."))
(when (> n 100)
  (princ "N is large."))    ; Good style.
```

When the main purpose is to return a value rather than take action, `cond` and `if` (with explicit `nil` in the else case) are preferred over when and `unless`, which implicitly return `nil` in the else case, `when` and `unless` are preferred when there is only one possibility, `if` (or, for some people, `cond)` when there are two, and `cond` when there are more than two:

```lisp
(defun tax-bracket (income)
  "Determine what percent tax should be paid for this income."
  (cond ((< income 10000.00) 0.00)
     ((< income 30000.00) 0.20)
     ((< income 50000.00) 0.25)
     ((< income 70000.00) 0.30)
     (t             .35)))
```

If there are several tests comparing an expression to constants, then case is appropriate.
A case form looks like:

`  (case`*expression*

      (*match result*...)...)

The *expression* is evaluated and compared to each successive *match*.
As soon as one is `eql`, the *result* expressions are evaluated and the last one is returned.
Note that the *match* expressions are *not* evaluated.
If a *match* expression is a list, then case tests if the *expression* is `eql` to any member of the list.
If a *match* expression is the symbol `otherwise` (or the symbol `t),` then it matches anything.
(It only makes sense for this `otherwise` clause to be the last one.)

There is also another special form, `typecase,` which compares the type of an expression against several possibilities and, like `case`, chooses the first clause that matches.
In addition, the special forms `ecase` and `etypecase` are just like `case` and `typecase` except that they signal an error if there is no match.
You can think of the `e` as standing for either "exhaustive" or "error." The forms `ccase` and `ctypecase` also signal errors, but they can be continuable errors (as opposed to fatal errors): the user is offered the chance to change the expression to something that satisfies one of the matches.
Here are some examples of case forms and their cond equivalents:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `(case x` | `(cond` |
|   `(1 10)` |   `((eql x 1) 10)` |
|   `(2 20))` |   `((eql x 2) 20))` |
| `(typecase x` | `(cond` |
|   `(number (abs x))` |   `((typep x 'number) (abs x))` |
|   `(list (length x)))` |   `((typep x 'list) (length x)))` |
| `(ecase x` | `(cond` |
|   `(1 10)` |   `((eql x 1) 10)` |
|   `(2 20))` |   `((eql x 2) 20)` |
| |   `(t (error "no valid case")))` |
| `(etypecase x` | `(cond` |
|   `(number (abs x))` |   `((typep x 'number) (abs x))` |
|   `(list (length x)))` |   `((typep x 'list) (length x))` |
| |   `(t (error "no valid typecase")))` |

### Special Forms for Dealing with Variables and Places
{:#s0030}
{:.h2hd}

The special form `setf` is used to assign a new value to a variable or *place*, much as an assignment statement with = or : = is used in other languages.
A place, or *generalized variable* is a name for a location that can have a value stored in it.
Here is a table of corresponding assignment forms in Lisp and Pascal:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `;; Lisp` | `/* Pascal */` |
| `(setf x 0)` | `x := 0;` |
| `(setf (aref A i j) 0)` | `A[i,j] := 0;` |
| `(setf (rest list) nil)` | `list^.rest := nil;` |
| `(setf (name-middle b) 'Q)` | `b\middle := "Q";` |

`setf` can be used to set a component of a structure as well as to set a variable.
In languages like Pascal, the expressions that can appear on the left-hand side of an assignment statement are limited by the syntax of the language.
In Lisp, the user can extend the expressions that are allowed in a `setf` form using the special forms `defsetf` or `define-setf-method`.
These are introduced on [pages 514](B9780080571157500157.xhtml#p514) and [884](B978008057115750025X.xhtml#p884) respectively.

There are also some built-in functions that modify places.
For example, (`rplacd list nil`) has the same effect as (`setf` (`rest list`) `nil`), except that it returns `list` instead of `nil`.
Most Common Lisp programmers prefer to use the `setf` forms rather than the specialized functions.

If you only want to set a variable, the special form `setq` can be used instead.
In this book I choose to use `setf` throughout, opting for consistency over specificity.

The discussion in this section makes it seem that variables (and slots of structures) are assigned new values all the time.
Actually, many Lisp programs do no assignments whatsoever.
It is very common to use Lisp in a functional style where new variables may be introduced, but once a new variable is established, it never changes.
One way to introduce a new variable is as a parameter of a function.
It is also possible to introduce local variables using the special form `let`.
Following are the general `let` form, along with an example.
Each variable is bound to the corresponding value, and then the body is evaluated:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| (let ((*variable value*)...)  *body*...) | `    (let ((x 40)`        `(y (+ 1 1)))`   `(+ x y))` => `42` |

Defining a local variable with a `let` form is really no different from defining parameters to an anonymous function.
The former is equivalent to:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| ((lambda (*variable*... )    *body*... ) *value*...) | `   ((lambda (x y)`       `(+ x y))` `40` `(+ 1 1))` |

First, all the values are evaluated.
Then they are bound to the variables (the parameters of the lambda expression), and finally the body is evaluated, using those bindings.

The special form `let`* is appropriate when you want to use one of the newly introduced variables in a subsequent *value* computation.
For example:

```lisp
(let* ((x 6)
   (y (* x x)))
(+ x y))` => `42
```

We could not have used `let` here, because then the variable `x` would be unbound during the computation of `y`'s value.

**Exercise 3.1 [m]** Show a `lambda` expression that is equivalent to the above `let`* expression.
You may need more than one `lambda.`

Because lists are so important to Lisp, there are special forms for adding and deleting elements from the front of a list-in other words, for treating a list as a stack.
If `list` is the name of a location that holds a list, then (`push`*x*`list`) will change `list` to have *x* as its first element, and (`pop list`) will return the first element and, as a side-effect, change `list` to no longer contain the first element.
`push` and `pop` are equivalent to the following expressions:

```lisp
(push x list)` = `(setf list (cons x list))
(pop list)`  = `(let ((result (first list)))
                          (setf list (rest list))
                          result)
```

Just as a list can be used to accumulate elements, a running sum can be used to accumulate numbers.
Lisp provides two more special forms, `incf` and `decf`, that can be used to increment or decrement a sum.
For both forms the first argument must be a location (a variable or other `setf`-able form) and the second argument, which is optional, is the number to increment or decrement by.
For those who know C, (`incf x`) is equivalent to `++x`, and (`incf x 2`) is equivalent to `x+=2`.
In Lisp the equivalence is:

```lisp
(incf x)` = `(incf x 1)` = `(setf x (+ x 1))
(decf x)` = `(decf x 1)` = `(setf x (- x 1))
```

When the location is a complex form rather than a variable, Lisp is careful to expand into code that does not evaluate any subform more than once.
This holds for `push`, `pop`, `incf,` and `decf`.
In the following example, we have a list of players and want to decide which player has the highest score, and thus has won the game.
The structure `player` has slots for the player's score and number of wins, and the function `determine` - `winner` increments the winning player's `wins` field.
The expansion of the `incf` form binds a temporary variable so that the sort is not done twice.

```lisp
(defstruct player (score 0) (wins 0))
(defun determine-winner (players)
   "Increment the WINS for the player with highest score."
   (incf (player-wins (first (sort players #'>
                  :key #'player-score)))))
=
(defun determine-winner (players)
   "Increment the WINS for the player with highest score."
   (let ((temp (first (sort players #'> :key #'player-score))))
      (setf (player-wins temp) (+ (player-wins temp) 1))))
```

### Functions and Special Forms for Repetition
{:#s0035}
{:.h2hd}

Many languages have a small number of reserved words for forming iterative loops.
For example, Pascal has `while, repeat,` and `for` statements.
In contrast, Common Lisp has an almost bewildering range of possibilities, as summarized below:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `dolist` | loop over elements of a list |
| `dotimes` | loop over successive integers |
| `do, do*` | general loop, sparse syntax |
| `loop` | general loop, verbose syntax |
| `mapc, mapcar` | loop over elements of lists(s) |
| `some, every` | loop over list until condition |
| `find, reduce,`*etc.* | more specific looping functions |
| *recursion* | general repetition |

To explain each possibility we will present versions of the function `length`, which returns the number of elements in a list.
First, the special form `dolist` can be used to iterate over the elements of a list.
The syntax is:

`(dolist (`*variable list optional-result*) *body...*)

This means that the body is executed once for each element of the list, with *variable* bound to the first element, then the second element, and so on.
At the end, `dolist` evaluates and returns the *optional-result* expression, or nil if there is no result expression.

Below is a version of `length` using `dolist`.
The `let` form introduces a new variable, `len`, which is initially bound to zero.
The `dolist` form then executes the body once for each element of the list, with the body incrementing `len` by one each time.
This use is unusual in that the loop iteration variable, `element`, is not used in the body.

```lisp
(defun lengthl (list)
 (let (len 0))       ;start with LEN=0
  (dolist (element list) ;and on each iteration
   (incf len))        ; increment LEN by 1
  len))           ;and return LEN
```

It is also possible to use the optional result of `dolist`, as shown below.
While many programmers use this style, I find that it is too easy to lose track of the result, and so I prefer to place the result last explictly.

```lisp
(defun lengthl.1 (list)        ;alternate version:
 (let ((len 0))         ;(not my preference)
  (dolist (element list len) ;uses len as result here
   (incf len))))
```

The function `mapc` performs much the same operation as the special form `dolist`.
In the simplest case, `mapc` takes two arguments, the first a function, the second a list.
It applies the function to each element of the list.
Here is `length` using `mapc`:

```lisp
(defun length2 (list)
 (let ((len 0))        ;start with LEN=0
  (mapc #'(lambda (element) ;and on each iteration
        (incf len))   ; increment LEN by 1
     list)
  len)) ;and return LEN
```

There are seven different mapping functions, of which the most useful are `mapc` and `mapcar`.
`mapcar` executes the same function calls as `mapc,` but then returns the results in a list.

There is also a `dotimes` form, which has the syntax:

(`dotimes` (*variable number optional-result*) *body...*)

and executes the body with *variable* bound first to zero, then one, all the way up to *number*-1 (for a total of *number* times).
Of course, `dotimes` is not appropriate for implementing `length`, since we don't know the number of iterations ahead of time.

There are two very general looping forms, `do` and `loop`.
The syntax of `do` is as follows:

(`do` ((*variable initial next*)*...*)

   (*exit-test result*)

 *body...*)

Each *variable* is initially bound to the *initial* value.
If *exit-test* is true, then *result* is returned.
Otherwise, the body is executed and each *variable* is set to the corresponding *next* value and *exit-test* is tried again.
The loop repeats until *exit-test* is true.
If a *next* value is omitted, then the corresponding variable is not updated each time through the loop.
Rather, it is treated as if it had been bound with a `let` form.

Hereis `length` implemented with `do`, using two variables, `len` to count the number of elements, and `l` to go down the list.
This is often referred to as *cdr-ing down a list,* because on each operation we apply the function `cdr` to the list.
(Actually, here we have used the more mnemonic name `rest` instead of `cdr`.) Note that the `do loop` has no body!
All the computation is done in the variable initialization and stepping, and in the end test.

```lisp
(defun length3 (list)
 (do ((len 0 (+ len 1))  ;start with LEN=0, increment
   (1 list (rest 1)))   ;... on each iteration
   ((null 1) len)))    ;(until the end of the list)
```

I find the `do` form a little confusing, because it does not clearly say that we are looping through a list.
To see that it is indeed iterating over the list requires looking at both the variable `l` and the end test.
Worse, there is no variable that stands for the current element of the list; we would need to say (`first l`) to get at it.
Both `dolist` and `mapc` take care of stepping, end testing, and variable naming automatically.
They are examples of the "be specific" principle.
Because it is so unspecific, `do` will not be used much in this book.
However, many good programmers use it, so it is important to know how to read `do loops`, even if you decide never to write one.

The syntax of `loop` is an entire language by itself, and a decidedly non-Lisp-like language it is.
Rather than list all the possibilities for `loop`, we will just give examples here, and refer the reader to *Common Lisp the Language*, 2d edition, or chapter 24.5 for more details.
Here are three versions of `length` using `loop`:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `(defun length4 (list)` | |
|  `(loop for element in list` | `;go through each element` |
| `  count t))` | `; counting each one` |
| `(defun length5 (list)` | |
| ` (loop for element in list` | `;go through each element` |
| `  summing 1))` | `; adding 1 each time` |
| `(defun length6 (list)` | |
| ` (loop with len = 0` | `;start with LEN=0` |
| `  until (null list)` | `;and (until end of list)` |
| `  for element = (pop list)` | `;on each iteration` |
| `  do (incf len)` | `; increment LEN by 1` |
| `  finally (return len)))` | `;and return LEN` |

Every programmer learns that there are certain kinds of loops that are used again and again.
These are often called *programming idioms* or *cliches.* An example is going through the elements of a list or array and doing some operation to each element.
In most languages, these idioms do not have an explicit syntactic marker.
Instead, they are implemented with a general loop construct, and it is up to the reader of the program to recognize what the programmer is doing.

Lisp is unusual in that it provides ways to explicitly encapsulate such idioms, and refer to them with explicit syntactic and functional forms.
`dolist` and `dotimes` are two examples of this-they both follow the "be specific" principle.
Most programmers prefer to use a `dolist` rather than an equivalent `do,` because it cries out "this loop iterates over the elements of a list." Of course, the corresponding `do` form also says the same thing-but it takes more work for the reader to discover this.

In addition to special forms like `dolist` and `dotimes,` there are quite a few functions that are designed to handle common idioms.
Two examples are `count-if,` which counts the number of elements of a sequence that satisfy a predicate, and `position-if,` which returns the index of an element satisfying a predicate.
Both can be used to implement `length.` In `length7` below, `count - if` gives the number of elements in `list` that satisfy the predicate `true.` Since `true` is defined to be always true, this gives the length of the list.

```lisp
(defun length7 (list)
 (count-if #'true list))
(defun true (x) t)
```

In `length8,` the function `position` - `if` finds the position of an element that satisfies the predicate true, starting from the end of the list.
This will be the very last element of the list, and since indexing is zero-based, we add one to get the length.
Admittedly, this is not the most straightforward implementation of `length.`

```lisp
(defun length8 (list)
 (if (null list)
   0
   (+ 1 (position-if #'true list :from-end t))))
```

A partial table of functions that implement looping idioms is given below.
These functions are designed to be flexible enough to handle almost all operations on sequences.
The flexibility cornes in three forms.
First, functions like mapcar can apply to an arbitrary number of lists, not just one:

```lisp
> (mapcar #'- '(1 2 3))` => `(-1 -2 -3)
> (mapcar #'+ '(1 2) '(10 20)) => (11 22)
> (mapcar #'+ '(1 2) '(10 20) '(100 200)) => (111 222)
```

Second, many of the functions accept keywords that allow the user to vary the test for comparing elements, or to only consider part of the sequence.

```lisp
> (remove 1 '(1 2 3 2 1 0 -1))` => `(2 3 2 0-1)
> (remove 1 '(1 2 3 2 1 0 -1) :key #'abs)` => `(2 3 2 0)
> (remove 1 '(1 2 3 2 1 0 -1) :test #'<)` => `(110 -1)
> (remove 1 '(123210-1) : start 4)` => `(1 2 3 2 0 -1)
```

Third, some have corresponding functions ending in -`if` or -`if`-not that take a predicate rather than an element to match against:

```lisp
> (remove-if #'oddp '(1 2 3 2 1 0 -1))` => `(2 2 0)
> (remove-if-not #'oddp '(1 2 3 2 1 0 -1))` => `(1 3 1 -1)
> (find-if #'evenp '(1 2 3 2 1 0 -1))` => `2
```

The following two tables assume these two values:

```lisp
(setf x '(a b c))
(setf y '(1 2 3))
```

The first table lists functions that work on any number of lists but do not accept keywords:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `(every #' oddp y)` | => `nil` | test if every element satisfies a predicate |
| `(some #' oddp y)` | => `t` | test if some element satisfies predicate |
| `(mapcar #'- y)` | => `(-1-2-3)` | apply function to each element and return result |
| `(mapc #'print y)` | *prints*`1 2 3` | perform operation on each element |

The second table lists functions that have `-if` and `-if-not` versions and also accept keyword arguments:

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `(member 2 y)` | =>`(2 3)` | see if element is in list |
| `(count 'b x)` | => 1 | count the number of matching elements |
| (`delete` 1 `y)` | => `(2 3)` | omit matching elements |
| `(find 2 y)` | => `2` | find first element that matches |
| `(position 'a x)` | => 0 | find index of element in sequence |
| `(reduce #'+ y)` | => `6` | apply function to succesive elements |
| `(remove 2 y)` | => (1 `3)` | like `delete`, but makes a new copy |
| `(substitute 4 2 y)` | => `(1 4 3)` | replace elements with new ones |

### Repetition through Recursion
{:#s0040}
{:.h2hd}

Lisp has gained a reputation as a "recursive" language, meaning that Lisp encourages programmers to write functions that call themselves.
As we have seen above, there is a dizzying number of functions and special forms for writing loops in Common Lisp, but it is also true that many programs handle repetition through recursion rather than with a syntactic loop.

One simple definition of `length` is "the empty list has length 0, and any other list has a length which is one more than the length of the rest of the list (after the first element)." This translates directly into a recursive function:

```lisp
(defun length9 (list)
 (if (null list)
   0
   (+ 1 (length9 (rest list)))))
```

This version of `length` arises naturally from the recursive definition of a list: "a list is either the empty list or an element consed onto another list." In general, most recursive functions derive from the recursive nature of the data they are operating on.
Some kinds of data, like binary trees, are hard to deal with in anything but a recursive fashion.
Others, like lists and integers, can be defined either recursively (leading to recursive functions) or as a sequence (leading to iterative functions).
In this book, I tend to use the "list-as-sequence" view rather than the "list-as-first-and- rest" view.
The reason is that defining a list as a first and a rest is an arbitrary and artificial distinction that is based on the implementation of lists that Lisp happens to use.
But there are many other ways to decompose a list.
We could break it into the last element and all-but-the-last elements, for example, or the first half and the second half.
The "list-as-sequence" view makes no such artificial distinction.
It treats all elements identically.

One objection to the use of recursive functions is that they are inefficient, because the compiler has to allocate memory for each recursive call.
This may be true for the function `1ength9`, but it is not necessarily true for all recursive calls.
Consider the following definition:

```lisp
(defun length10 (list)
 (length10-aux list 0))
(defun length10-aux (sublist len-so-far)
 (if (null sublist)
   len-so-far
   (length10-aux (rest sublist) (+ 1 len-so-far))))
```

`length10` uses `length10` - `aux` as an auxiliary function, passing it 0 as the length of the list so far.
`length10`-`aux` then goes down the list to the end, adding 1 for each element.
The invariant relation is that the length of the sublist plus `1en - so - far` always equals the length of the original list.
Thus, when the sublist is nil, then `1en-so-far` is the length of the original list.
Variables like `1en - so - far` that keep track of partial results are called *accumulators.* Other examples of functions that use accumulators include `flatten - all` on page 329; `one - unknown` on page 237; the Prolog predicates discussed on page 686; and `anonymous-variables-in` on pages 400 and 433, which uses two accumulators.

The important difference between `length9` and `length10` is *when* the addition is done.
In `length9`, the function calls itself, then returns, and then adds 1.
In `length10`-`aux`, the function adds 1, then calls itself, then returns.
There are no pending operations to do after the recursive call returns, so the compiler is free to release any memory allocated for the original call before making the recursive call.
`length10`-`aux` is called a *tail-recursive* function, because the recursive call appears as the last thing the function does (the tail).
Many compilers will optimize tail-recursive calls, although not all do.
([Chapter 22](B9780080571157500224.xhtml) treats tail-recursion in more detail, and points out that Scheme compilers guarantee that tail-recursive calls will be optimized.)

Some find it ugly to introduce 1 `length10`- `aux`.
For them, there are two alternatives.
First, we could combine 1 `length10` and 1 `length10`-`aux` into a single function with an optional parameter:

```lisp
(defun length11 (list &optional (len-so-far 0))
 (if (null list)
   len-so-far
   (length11 (rest list) (+ 1 len-so-far))))
```

Second, we could introduce a *local* function inside the definition of the main function.
This is done with the special form `labels`:

```lisp
(defun length12 (the-list)
 (labels
  ((length13 (list len-so-far)
   (if (null list)
    len-so-far
    (length13 (rest list) (+ 1 len-so-far)))))
  (length13 the-list 0)))
```

In general, a `1abels` form (or the similar `flet` form) can be used to introduce one or more local functions.
It has the following syntax:

```lisp
(labels
```

 ((*function-name* (*parameter...*) *function-body*)*...*)

 *body-of-labels)*

### Other Special Forms
{:#s0045}
{:.h2hd}

A few more special forms do not fit neatly into any category.
We have already seen the two special forms for creating constants and functions, `quote` and `function.` These are so common that they have abbreviations: 'x for `(quote x`) and `#'f` for `(function f).`

The special form `progn` can be used to evaluate a sequence of forms and return the value of the last one:

```lisp
(progn (setf x 0) (setf x (+ x 1)) x)` => `1
```

`progn` is the equivalent of a `begin`... `end` block in other languages, but it is used very infrequently in Lisp.
There are two reasons for this.
First, programs written in a functional style never need a sequence of actions, because they don't have side effects.
Second, even when side effects are used, many special forms allow for a body which is a sequence-an implicit `progn.` I can only think of three places where a `progn` is justified.
First, to implement side effects in a branch of a two-branched conditional, one could use either an `if` with a `progn,` or a cond:

```lisp
(if (> x 100) (cond ((> x 100)
   (progn (print "too big")              (print "too big")
       (setf x 100)) (setf x 100))
   x) (t x))
```

If the conditional had only one branch, then `when` or `unless` should be used, since they allow an implicit `progn`.
If there are more than two branches, then `cond` should be used.

Second, `progn` is sometimes needed in macros that expand into more than one top-level form, as in the `defun*` macro on page 326, [section 10.3](B9780080571157500108.xhtml#s0020).
Third, a progn is sometimes needed in an `unwind-protect`, an advanced macro.
An example of this is the `with-resource` macro on [page 338](B9780080571157500108.xhtml#p338), [section 10.4](B9780080571157500108.xhtml#s0025).

The forms `trace` and `untrace` are used to control debugging information about entry and exit to a function:

```lisp
> (trace length9)` => `(LENGTH9)
```

`> (length9 '(a b c))`=>

```lisp
(1 ENTER LENGTH9: (ABC))
 (2 ENTER LENGTH9: (B C))
  (3 ENTER LENGTH9: (C))
   (4 ENTER LENGTH9: NIL)
   (4 EXIT LENGTH9: 0)
  (3 EXIT LENGTH9: 1)
 (2 EXIT LENGTH9: 2)
(1 EXIT LENGTH9: 3)
3
> (untrace length9) => (LENGTH9)
> (length9 '(a b c))` => `3
```

Finally, the special form `return` can be used to break out of a block of code.
Blocks are set up by the special form `block`, or by the looping forms `(do, do*, dolist, dotimes`, or `loop`).
For example, the following function computes the product of a list of numbers, but if any number is zero, then the whole product must be zero, so we immediately return zero from the `dolist` loop.
Note that this returns from the `dolist` only, not from the function itself (although in this case, the value returned by `dolist` becomes the value returned by the function, because it is the last expression in the function).
I have used uppercase letters in `RETURN` to emphasize the fact that it is an unusual step to exit from a loop.

```lisp
(defun product (numbers)
  "Multiply all the numbers together to compute their product."
  (let ((prod 1))
    (dolist (n numbers prod)
     (if (= n 0)
      (RETURN 0)
      (setf prod (* n prod))))))
```

### Macros
{:#s0050}
{:.h2hd}

The preceding discussion has been somewhat cavalier with the term "special form." Actually, some of these special forms are really *macros*, forms that the compiler expands into some other code.
Common Lisp provides a number of built-in macros and allows the user to extend the language by defining new macros.
(There is no way for the user to define new special forms, however.)

Macros are defined with the special form `defmacro`.
Suppose we wanted to define a macro, `while`, that would act like the `while` loop statement of Pascal.
Writing a macro is a four-step process:

*  Decide if the macro is really necessary.

*  Write down the syntax of the macro.

*  Figure out what the macro should expand into.

*  Use `defmacro` to implement the syntax/expansion correspondence.

The first step in writing a macro is to recognize that every time you write one, you are defining a new language that is just like Lisp except for your new macro.
The programmer who thinks that way will rightfully be extremely frugal in defining macros.
(Besides, when someone asks, "What did you get done today?" it sounds more impressive to say "I defined a new language and wrote a compiler for it" than to say "I just hacked up a couple of macros.") Introducing a macro puts much more memory strain on the reader of your program than does introducing a function, variable or data type, so it should not be taken lightly.
Introduce macros only when there is a clear need, and when the macro fits in well with your existing system.
As C.A.R.
Hoare put it, "One thing the language designer should not do is to include untried ideas of his own."

The next step is to decide what code the macro should expand into.
It is a good idea to follow established Lisp conventions for macro syntax whenever possible.
Look at the looping macros `(dolist, dotimes, do-symbols),` the defining macros `(defun, defvar, defparameter, defstruct),` or the the I/O macros `(with-open-file, with-open-stream, with-input-from-string),` for example.
If you follow the naming and syntax conventions for one of these instead of inventing your own conventions, you'll be doing the reader of your program a favor.
For `while,` a good syntax is:

(`while`*test body...*)

The third step is to write the code that you want a macro call to expand into:

```lisp
(loop
  (unless`*test*`(return nil))
```

  *body*)

The final step is to write the definition of the macro, using `defmacro.
A defmacro` form is similar to a `defun` in that it has a parameter list, optional documentation string, and body.
There are a few differences in what is allowed in the parameter list, which will be covered later.
Here is a definition of the macro `while`, which takes a test and a body, and builds up the `loop` code shown previously:

```lisp
(defmacro while (test &rest body)
  "Repeat body while test is true."
  (list* 'loop
  (list 'unless test '(return nil))
      body))
```

(The function `list`* is like `list`, except that the last argument is appended onto the end of the list of the other arguments.) We can see what this macro expands into by using `macroexpand`, and see how it runs by typing in an example:

```lisp
> (macroexpand-1 '(while (< i 10)
        (print (* i i))
```

        `(setf i (+ i 1))))`=>

```lisp
(LOOP (UNLESS (< I 10) (RETURN NIL))
   (PRINT (* I I))
   (SETF I (+ I 1)))
> (setf i 7) =>7
> (while (< i 10)
  (print (* i i))
  (setf i (+ i 1)))
49
64
81
NIL
```

[Section 24.6](B9780080571157500248.xhtml) (page 853) describes a more complicated macro and some details on the pitfalls of writing complicated macros (page 855).

### Backquote Notation
{:#s0060}
{:.h2hd}

The hardest part about defining `while` is building the code that is the expansion of the macro.
It would be nice if there was a more immediate way of building code.
The following version of `while` following attempts to do just that.
It defines the local variable `code` to be a template for the code we want, and then substitutes the real values of the variables test and body for the placeholders in the code.
This is done with the function `subst`; (`subst`*new old tree*) substitutes *new* for each occurrence of *old* anywhere within *tree.*

```lisp
(defmacro while (test &rest body)
 "Repeat body while test is true."
 (let ((code '(loop (unless test (return nil)) . body)))
   (subst test 'test (subst body 'body code))))
```

The need to build up code (and noncode data) from components is so frequent that there is a special notation for it, the *backquote* notation.
The backquote character `"'"` is similar to the quote character `"'"`.
A backquote indicates that what follows is *mostly* a literal expression but may contain some components that are to be evaluated.
Anything marked by a leading comma `","` is evaluated and inserted into the structure, and anything marked with a leading `",@"` must evaluate to a list that is spliced into the structure: each element of the list is inserted, without the top-level parentheses.
The notation is covered in more detail in [section 23.5](B9780080571157500236.xhtml#s0030).
Here we use the combination of backquote and comma to rewrite `while`:

```lisp
(defmacro while (test &rest body)
 "Repeat body while test is true."
 '(loop (unless ,test (return nil))
     ,@body))
```

Here are some more examples of backquote.
Note that at the end of a list, `",@"` has the same effect as `"."` followed by `","`.
In the middle of a list, only `",@"`is a possibility.

```lisp
> (setf testl '(a test)) => (A TEST)
> '(this is ,test1) => (THIS IS (A TEST))
> '(this is ,@test1) => (THIS IS A TEST)
> '(this is . ,test1) => (THIS IS A TEST)
> '(this is ,@test1 -- this is only ,@testl) =>
(THIS IS A TEST -- THIS IS ONLY A TEST)
```

This completes the section on special forms and macros.
The remaining sections of this chapter give an overview of the important built-in functions in Common Lisp.

## 3.3 Functions on Lists
{:#s0065}
{:.h1hd}

For the sake of example, assume we have the following assignments:

```lisp
(setf x '(a b c))
(setf y '(1 2 3))
```

The most important functions on lists are summarized here.
The more complicated ones are explained more thoroughly when they are used.

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| `(first x)` | => `a` | first element of a list |
| `(second x)` | `=> b` | second element of a list |
| `(third x)` | => `c` | third element of a list |
| `(nth 0 x)` | => `a` | nth element of a list, `0`-based |
| `(rest x)` | => `(b c)` | ail but the first element |
| `(car x)` | => `a` | another name for the first element of a list |
| `(cdr x)` | => `(b c)` | another name for all but the first element |
| `(last x)` | => `(c)` | last cons cell in a list |
| `(length x)` | => 3 | number of elements in a list |
| `(reverse x)` | => `(c b a)` | puts list in reverse order |
| `(cons 0 y)` | => `(0 1 2 3)` | add to front of list |
| `(append x y)` | => `(a b c 1 2 3)` | append together elements |
| `(list x y)` | => `((a b c) (1 2 3))` | make a new list |
| `(list* 1 2 x)` | => `(1 2 a b` c) | append last argument to others |
| `(null nil)` | => `T` | predicate is true of the empty list |
| `(null x)` | => `nil` | ... and false for everything else |
| `(listp x)` | => `T` | predicate is true of any list, including `nil` |
| `(listp 3)` | => `nil` | ... and is false for nonlists |
| `(consp x)` | => `t` | predicate is true of non-nil lists |
| `(consp nil)` | => `nil` | ... and false for atoms, including `nil` |
| `(equal x x)` | => `t` | true for lists that look the same |
| `(equal x y)` | `nil` | ... and false for lists that look different |
| `(sort y #'>)` | => `(3 2 1)` | sort a list according to a comparison function |
| `(subseq x 1 2)` | => `(B)` | subsequence with given start and end points |

We said that (`cons`*a b*) builds a longer list by adding element *a* to the front of list *b,* but what if *b* is not a list?
This is not an error; the result is an object *x* such that (`first`*x*) => *a* (`rest`*x*) => *b,* and where *x* prints as (*a* . *b*).
This is known as *dotted pair* notation.
If *b* is a list, then the usual list notation is used for output rather than the dotted pair notation.
But either notation can be used for input.

So far we have been thinking of lists as sequences, using phrases like "a list of three elements." The list is a convenient abstraction, but the actual implementation of lists relies on lower-level building blocks called *cons cells.* A cons cell is a data structure with two fields: a first and a rest.
What we have been calling "a list of three elements" can also be seen as a single cons cell, whose first field points to the first element and whose rest field points to another cons cell that is a cons cell representing a list of two elements.
This second cons cell has a rest field that is a third cons cell, one whose rest field is nil.
All proper lists have a last cons cell whose rest field is nil.
[Figure 3.1](#f0010) shows the cons cell notation for the three-element list (`one two three`), as well as for the result of (`cons 'one 'two`).

![f03-01-9780080571157](images/B9780080571157500030/f03-01-9780080571157.jpg)     
Figure 3.1
!!!(span) {:.fignum}
Cons Cell Diagrams
**Exercise 3.2 [s]** The function cons can be seen as a special case of one of the other functions listed previously.
Which one?

**Exercise 3.3 [m]** Write a function that will print an expression in dotted pair notation.
Use the built-in function `princ` to print each component of the expression.

**Exercise 3.4 [m]** Write a function that, like the regular `print` function, will print an expression in dotted pair notation when necessary but will use normal list notation when possible.

## 3.4 Equality and Internal Representation
{:#s0070}
{:.h1hd}

In Lisp there are five major equality predicates, because not all objects are created equally equal.
The numeric equality predicate, =, tests if two numbers are the same.
It is an error to apply = to non-numbers.
The other equality predicates operate on any kind of object, but to understand the difference between them, we need to understand some of the internals of Lisp.

When Lisp reads a symbol in two different places, the result is guaranteed to be the exact same symbol.
The Lisp system maintains a symbol table that the function read uses to map between characters and symbols.
But when a list is read (or built) in two different places, the results are *not* identically the same, even though the corresponding elements may be.
This is because `read` calls `cons` to build up the list, and each call to `cons` returns a new cons cell.
[Figure 3.2](#f0015) shows two lists, `x` and `Y`, which are both equal to (`one two`), but which are composed of different cons cells, and hence are not identical.
[Figure 3.3](#f0020) shows that the expression (`rest x`) does not generate new cons cells, but rather shares structure with `x`, and that the expression (`cons ' zero x`) generates exactly one new cons cell, whose rest is `x`.

![f03-02-9780080571157](images/B9780080571157500030/f03-02-9780080571157.jpg)     
Figure 3.2
!!!(span) {:.fignum}
Equal But Nonidentical Lists
![f03-03-9780080571157](images/B9780080571157500030/f03-03-9780080571157.jpg)     
Figure 3.3
!!!(span) {:.fignum}
Parts of Lists
When two mathematically equal numbers are read (or computed) in two places, they may or may not be the same, depending on what the designers of your implementation felt was more efficient.
In most systems, two equal fixnums will be identical, but equal numbers of other types will not (except possibly short floats).
Common Lisp provides four equality predicates of increasing generality.
All four begin with the letters `eq`, with more letters meaning the predicate considers more objects to be equal.
The simplest predicate is `eq`, which tests for the exact same object.
Next, `eql` tests for objects that are either `eq` or are equivalent numbers.
`equal` tests for objects that are either `eql` or are lists or strings with `eql` elements.
Finally, `equalp` is like `equal` except it also matches upper- and lowercase characters and numbers of different types.
The following table summarizes the results of applying each of the four predicates to various values of *x* and `y`.
The ? value means that the result depends on your implementation: two integers that are `eql` may or may not be `eq`.

!!!(table)

| []() | | | | | | | | | |
|---|---|---|---|---|---|---|---|---|---|
| *x* | *y* | `eq` | `eql` | `equal` | `equalp` |
| `'X` | `'x` | `T` | `T` | `T` | `T` |
| `'0` | `'0` | `?` | `T` | `T` | `T` |
| `'(x)` | `'(x)` | `nil` | `nil` | `T` | `T` |
| `'"xy"` | `'"xy"` | `nil` | `nil` | `T` | `T` |
| `'"Xy"` | `'"xY"` | `nil` | `nil` | `nil` | `T` |
| `'0` | `'0.0` | `nil` | `nil` | `nil` | `T` |
| `'0` | `'1` | `nil` | `nil` | `nil` | `nil` |

![t0065](images/B9780080571157500030/t0065.png)

In addition, there are specialized equality predicates such as =, `tree-equal, char-equal,` and `string-equal,` which compare numbers, trees, characters, and strings, respectively.

## 3.5 Functions on Sequences
{:#s0075}
{:.h1hd}

Common Lisp is in a transitional position halfway between the Lisps of the past and the Lisps of the future.
Nowhere is that more apparent than in the sequence functions.
The earliest Lisps dealt only with symbols, numbers, and lists, and provided list functions like `append` and `length.` More modem Lisps added support for vectors, strings, and other data types, and introduced the term *sequence* to refer to both vectors and lists.
(A vector is a one-dimensional array.
It can be represented more compactly than a list, because there is no need to store the rest pointers.
It is also more efficient to get at the nth element of a vector, because there is no need to follow a chain of pointers.) Modem Lisps also support strings that are vectors of characters, and hence also a subtype of sequence.

With the new data types came the problem of naming functions that operated on them.
In some cases, Common Lisp chose to extend an old function: `length` can apply to vectors as 
Download .txt
gitextract_ci22_or4/

├── .gitignore
├── LICENSE
├── PAIP-alpha.epub
├── PAIP-safari.md
├── PAIP.txt
├── README.md
├── docs/
│   ├── .nojekyll
│   ├── README.md
│   ├── _coverpage.md
│   ├── _sidebar.md
│   ├── about-scan.md
│   ├── about.md
│   ├── appendix.md
│   ├── bibliography.md
│   ├── chapter1.md
│   ├── chapter10.md
│   ├── chapter11.md
│   ├── chapter12.md
│   ├── chapter13.md
│   ├── chapter14.md
│   ├── chapter15.md
│   ├── chapter16.md
│   ├── chapter17.md
│   ├── chapter18.md
│   ├── chapter19.md
│   ├── chapter2.md
│   ├── chapter20.md
│   ├── chapter21.md
│   ├── chapter22.md
│   ├── chapter23.md
│   ├── chapter24.md
│   ├── chapter25.md
│   ├── chapter3.md
│   ├── chapter4.md
│   ├── chapter5.md
│   ├── chapter6.md
│   ├── chapter7.md
│   ├── chapter8.md
│   ├── chapter9.md
│   ├── code.md
│   ├── css/
│   │   └── github.css
│   ├── frontmatter.md
│   ├── images/
│   │   ├── chapter14/
│   │   │   ├── diagram-14-02.drawio
│   │   │   ├── fig-14-01.drawio
│   │   │   ├── si1_e.tex
│   │   │   └── si2_e.tex
│   │   ├── chapter15/
│   │   │   ├── si1_e.tex
│   │   │   ├── si2_e.tex
│   │   │   ├── si3_e.tex
│   │   │   ├── si4_e.tex
│   │   │   ├── si5_e.tex
│   │   │   └── si7_e.tex
│   │   ├── chapter16/
│   │   │   ├── fig-16-02.drawio
│   │   │   └── si1_e.tex
│   │   ├── chapter17/
│   │   │   ├── fig-17-01.drawio
│   │   │   ├── fig-17-02.drawio
│   │   │   ├── fig-17-03.drawio
│   │   │   ├── fig-17-04.drawio
│   │   │   ├── fig-17-07.drawio
│   │   │   ├── fig-17-08.drawio
│   │   │   ├── fig-17-09.drawio
│   │   │   ├── fig-17-10.drawio
│   │   │   ├── fig-17-11.drawio
│   │   │   └── fig-17-12.drawio
│   │   ├── chapter18/
│   │   │   ├── diagram-18-01.drawio
│   │   │   ├── diagram-18-02.drawio
│   │   │   ├── diagram-18-03.drawio
│   │   │   ├── diagram-18-04.drawio
│   │   │   ├── diagram-18-05.drawio
│   │   │   ├── fig-18-01.drawio
│   │   │   ├── fig-18-02.drawio
│   │   │   └── fig-18-04.drawio
│   │   ├── chapter2/
│   │   │   └── fig-02-01.drawio
│   │   ├── chapter3/
│   │   │   ├── fig-03-01.drawio
│   │   │   ├── fig-03-02.drawio
│   │   │   ├── fig-03-03.drawio
│   │   │   └── fig-03-04.drawio
│   │   ├── chapter4/
│   │   │   ├── diagram-04-01.drawio
│   │   │   ├── diagram-04-02.drawio
│   │   │   ├── diagram-04-03.drawio
│   │   │   ├── diagram-04-04.drawio
│   │   │   ├── diagram-04-05.drawio
│   │   │   ├── diagram-04-06.drawio
│   │   │   └── diagram-04-09.drawio
│   │   ├── chapter6/
│   │   │   ├── diagram-06-01.drawio
│   │   │   ├── fig-06-01.drawio
│   │   │   ├── fig-06-02.drawio
│   │   │   ├── fig-06-03.drawio
│   │   │   ├── fig-06-04.drawio
│   │   │   └── fig-06-05.drawio
│   │   └── chapter9/
│   │       ├── si1_e.tex
│   │       ├── si2_e.tex
│   │       └── si3_e.tex
│   ├── index.html
│   ├── js/
│   │   └── highlight-lisp.js
│   ├── markdown-help.md
│   └── preface.md
├── lisp/
│   ├── auxfns.lisp
│   ├── clos.lisp
│   ├── cmacsyma.lisp
│   ├── compile1.lisp
│   ├── compile2.lisp
│   ├── compile3.lisp
│   ├── compopt.lisp
│   ├── edge-tab.lisp
│   ├── eliza-pm.lisp
│   ├── eliza.lisp
│   ├── eliza1.lisp
│   ├── examples.lisp
│   ├── gps-srch.lisp
│   ├── gps.lisp
│   ├── gps1.lisp
│   ├── grammar.lisp
│   ├── interp1.lisp
│   ├── interp2.lisp
│   ├── interp3.lisp
│   ├── intro.lisp
│   ├── krep.lisp
│   ├── krep1.lisp
│   ├── krep2.lisp
│   ├── lexicon.lisp
│   ├── loop.lisp
│   ├── macsyma.lisp
│   ├── macsymar.lisp
│   ├── mycin-r.lisp
│   ├── mycin.lisp
│   ├── open-pdf.lisp
│   ├── othello.lisp
│   ├── othello2.lisp
│   ├── overview.lisp
│   ├── patmatch.lisp
│   ├── prolog.lisp
│   ├── prolog1.lisp
│   ├── prologc.lisp
│   ├── prologc1.lisp
│   ├── prologc2.lisp
│   ├── prologcp.lisp
│   ├── search.lisp
│   ├── simple.lisp
│   ├── student.lisp
│   ├── syntax1.lisp
│   ├── syntax2.lisp
│   ├── syntax3.lisp
│   ├── tutor.lisp
│   ├── unifgram.lisp
│   ├── unify.lisp
│   └── waltz.lisp
├── meta/
│   ├── metadata.xml
│   ├── stylesheet.css
│   └── title.txt
├── paip.asd
└── scripts/
    ├── filter-ascii.rb
    ├── httpd-py.sh
    ├── httpd-rb.sh
    ├── make-code-blocks.rb
    ├── make-epub.sh
    ├── make-pdf-from-epub.sh
    ├── markdown-to-text.sh
    ├── one-offs/
    │   ├── add-page-anchors.rb
    │   └── linkify_page_numbers.rb
    ├── prepare-for-merge.rb
    ├── split-chapters-markdown.rb
    └── split-chapters.rb
Download .txt
SYMBOL INDEX (4 symbols across 2 files)

FILE: scripts/make-code-blocks.rb
  function code? (line 8) | def code?(str)
  function convert_code_line (line 20) | def convert_code_line(str)
  function convert_code_block (line 27) | def convert_code_block(arr)

FILE: scripts/one-offs/linkify_page_numbers.rb
  function parse_chapter_file (line 8) | def parse_chapter_file(line)
Condensed preview — 163 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,376K chars).
[
  {
    "path": ".gitignore",
    "chars": 233,
    "preview": ".DS_Store\n.byebug_history\n\n# from splitting chapters\ndocs/paradigmsofartificialintelligenceprogramming.md\ndocs/copyright"
  },
  {
    "path": "LICENSE",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2018 Peter Norvig\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "PAIP-safari.md",
    "chars": 1979987,
    "preview": "# Paradigms of Artificial Intelligence Programming\n{:.book_title}\n\n## Case Studies in Common Lisp\n{:.book_subtitle}\n\nFir"
  },
  {
    "path": "PAIP.txt",
    "chars": 1796967,
    "preview": "## Frontmatter\nParadigms of \nArtificial Intelligence \nProgramming: \n\nCASE STUDIES IN COMMON LISP \n\nPeter Norvig \n\nMORGAN"
  },
  {
    "path": "README.md",
    "chars": 10665,
    "preview": "\n<img src=\"paip-cover.png\" title=\"Paradigms of Artificial Intelligence Programming\" width=413>\n\nThis is an open-source r"
  },
  {
    "path": "docs/.nojekyll",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/README.md",
    "chars": 13112,
    "preview": "\n# *Paradigms of Artificial Intelligence Programming*\n\n![PAIP](https://norvig.com/paip-cover.gif)\n\n# Table of Contents\n\n"
  },
  {
    "path": "docs/_coverpage.md",
    "chars": 241,
    "preview": "![logo](_media/paip-cover.gif)\n\n# Paradigms of Artificial Intelligence Programming\n\n> Case Studies in Common Lisp\n\n* Pet"
  },
  {
    "path": "docs/_sidebar.md",
    "chars": 1535,
    "preview": "<!-- book/_sidebar.md -->\n\n* [Home](/)\n* [Preface](preface.md)\n* [Chapter 01 - Introduction to Lisp](chapter1.md)\n* [Cha"
  },
  {
    "path": "docs/about-scan.md",
    "chars": 1626,
    "preview": "# About this book\n\nThis book, \"Paradigms of Artificial Intelligence Programming\", was first published in 1992.\nThe right"
  },
  {
    "path": "docs/about.md",
    "chars": 852,
    "preview": "# About this book\n\nThis book, \"Paradigms of Artificial Intelligence Programming\", was first published in 1992.\nThe right"
  },
  {
    "path": "docs/appendix.md",
    "chars": 9194,
    "preview": "# Appendix\n## Obtaining the Code in this Book\n### FTP: The File Transfer Protocol\n\nFTP is a file transfer protocol that "
  },
  {
    "path": "docs/bibliography.md",
    "chars": 34242,
    "preview": "# Bibliography\n\nAbelson, Harold, Sussman Gerald J., Sussman Julie.\n*Structure and Interpretation of Computer Programs.* "
  },
  {
    "path": "docs/chapter1.md",
    "chars": 67002,
    "preview": "# Chapter 1\n## Introduction to Lisp\n\n> You think you know when you learn, are more sure when you can write, even more wh"
  },
  {
    "path": "docs/chapter10.md",
    "chars": 66029,
    "preview": "# Chapter 10\n## Low-Level Efficiency Issues\n\n> There are only two qualities in the world: efficiency and inefficiency; a"
  },
  {
    "path": "docs/chapter11.md",
    "chars": 84182,
    "preview": "# Chapter 11\n## Logic Programming\n\n> A language that doesn't affect the way you think about programming is not worth kno"
  },
  {
    "path": "docs/chapter12.md",
    "chars": 87092,
    "preview": "# Chapter 12\n## Compiling Logic Programs\n\nThe end of [chapter 11](chapter11.md) introduced a new, more efficient represe"
  },
  {
    "path": "docs/chapter13.md",
    "chars": 58652,
    "preview": "# Chapter 13\n## Object-Oriented Programming\n\nThe programs in this book cover a wide range of problems.\nIt is only natura"
  },
  {
    "path": "docs/chapter14.md",
    "chars": 99198,
    "preview": "# Chapter 14\n## Knowledge Representation and Reasoning\n\n> *Knowledge itself is power.* \\\n> -Francis Bacon (1561-1626)\n\n>"
  },
  {
    "path": "docs/chapter15.md",
    "chars": 45133,
    "preview": "# Chapter 15\n## Symbolic Mathematics with Canonical Forms\n\n> Anything simple always interests me.\n\n> -David Hockney\n\n[Ch"
  },
  {
    "path": "docs/chapter16.md",
    "chars": 69287,
    "preview": "# Chapter 16\n## Expert Systems\n\n> An expert is one who knows more and more about less and less.\n\n> -Nicholas Murray Butl"
  },
  {
    "path": "docs/chapter17.md",
    "chars": 50946,
    "preview": "# Chapter 17\n## Line-Diagram Labeling by Constraint Satisfaction\n\n> It is wrong to think of Waltz's work only as a state"
  },
  {
    "path": "docs/chapter18.md",
    "chars": 125283,
    "preview": "# Chapter 18\n## Search and the Game of Othello\n\n> In the beginner's mind there are endless possibilities; in the expert'"
  },
  {
    "path": "docs/chapter19.md",
    "chars": 60076,
    "preview": "# Chapter 19\n## Introduction to Natural Language\n\n> Language is everywhere.\nIt permeates our thoughts, mediates our rela"
  },
  {
    "path": "docs/chapter2.md",
    "chars": 24992,
    "preview": "# Chapter 2\n## A Simple Lisp Program\n\n> *Certum quod factum.* \\\n> (One is certain of only what one builds.)\n\n> -Giovanni"
  },
  {
    "path": "docs/chapter20.md",
    "chars": 59247,
    "preview": "# Chapter 20\n## Unification Grammars\n\nProlog was invented because Alain Colmerauer wanted a formalism to describe the gr"
  },
  {
    "path": "docs/chapter21.md",
    "chars": 70194,
    "preview": "# Chapter 21\n## A Grammar of English\n\n> Prefer geniality to grammar.\n\n> -Henry Watson Fowler\n\n> *The King's English* (19"
  },
  {
    "path": "docs/chapter22.md",
    "chars": 57987,
    "preview": "# Chapter 22\n## Scheme: An Uncommon Lisp\n\n> The best laid schemes o' mice an' men\n\n> -Robert Burns (1759-1796)\n\nThis cha"
  },
  {
    "path": "docs/chapter23.md",
    "chars": 96654,
    "preview": "# Chapter 23\n## Compiling Lisp\n\nMany textbooks show simple interpreters for Lisp, because they are simple to write, and "
  },
  {
    "path": "docs/chapter24.md",
    "chars": 58897,
    "preview": "# Chapter 24\n## ANSI Common Lisp\n\nThis chapter briefly covers some advanced features of Common Lisp that were not used i"
  },
  {
    "path": "docs/chapter25.md",
    "chars": 59849,
    "preview": "# Chapter 25\n## Troubleshooting\n\n> Perhaps if we wrote programs from childhood on, as adults we'd be able to read them.\n"
  },
  {
    "path": "docs/chapter3.md",
    "chars": 127656,
    "preview": "# Chapter 3\n## Overview of Lisp\n\n> No doubt about it.\nCommon Lisp is a *big* language.\n\n> -Guy L. Steele, Jr.\n\n> Forewor"
  },
  {
    "path": "docs/chapter4.md",
    "chars": 89448,
    "preview": "# Chapter 4\n## GPS: The General Problem Solver\n\n> *There are now in the world machines that think.*\n\n> -Herbert Simon\n\n>"
  },
  {
    "path": "docs/chapter5.md",
    "chars": 50087,
    "preview": "# Chapter 5\n## ELIZA: Dialog with a Machine\n\n> *It is said that to explain is to explain away.*\n\n> -Joseph Weizenbaum\n\n>"
  },
  {
    "path": "docs/chapter6.md",
    "chars": 85507,
    "preview": "# Chapter 6\n## Building Software Tools\n\n> *Man is a tool-using animal...Without tools he is nothing with tools he is all"
  },
  {
    "path": "docs/chapter7.md",
    "chars": 41946,
    "preview": "# Chapter 7\n## STUDENT: Solving Algebra Word Problems\n\n> *[This] is an example par excellence* of the power of using mea"
  },
  {
    "path": "docs/chapter8.md",
    "chars": 46916,
    "preview": "# Chapter 8\n## Symbolic Mathematics: A Simplification Program\n\n> *Our life is frittered away by detail....*\n\n> *Simplify"
  },
  {
    "path": "docs/chapter9.md",
    "chars": 104787,
    "preview": "# Chapter 9\n## Efficiency Issues\n\n> A Lisp programmer knows the value of everything, but the cost of nothing.\n\n> -Alan J"
  },
  {
    "path": "docs/code.md",
    "chars": 8741,
    "preview": "## Code highlighting\n\n\nHere I'm testing the code highlighing functionality\n\n```lisp\n;;; -*- Mode: Lisp; Syntax: Common-L"
  },
  {
    "path": "docs/css/github.css",
    "chars": 1655,
    "preview": "/**\n * Inspired by github's default code highlighting\n */\npre { white-space: pre; background-color: #f8f8f8; border: 1px"
  },
  {
    "path": "docs/frontmatter.md",
    "chars": 1500,
    "preview": "\n\n# Paradigms of Artificial Intelligence Programming\n## CASE STUDIES IN COMMON LISP\n## *Peter Norvig*\n\n<span align=\"cent"
  },
  {
    "path": "docs/images/chapter14/diagram-14-02.drawio",
    "chars": 985,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T08:46:41.027Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter14/fig-14-01.drawio",
    "chars": 2443,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-25T06:00:27.213Z\" agent=\"5.0 (Macintosh)\" etag=\"_r8HvNJs5grNyQO9Y-UF\" "
  },
  {
    "path": "docs/images/chapter14/si1_e.tex",
    "chars": 64,
    "preview": "(b_{0}=0) \\wedge (b_{1}=0) \\wedge (b_{2}=1) ... \\wedge (b_{n}=0)"
  },
  {
    "path": "docs/images/chapter14/si2_e.tex",
    "chars": 39,
    "preview": "\\sqrt{x} = y \\Rightarrow y \\times y = x"
  },
  {
    "path": "docs/images/chapter15/si1_e.tex",
    "chars": 46,
    "preview": "5 \\times x^{3} +b \\times x^{2} +c \\times x + 1"
  },
  {
    "path": "docs/images/chapter15/si2_e.tex",
    "chars": 66,
    "preview": "\\int ax^{2} + bx\\, dx = \\frac {ax^{3}}{3} + \\frac {bx^{2}}{2} + c."
  },
  {
    "path": "docs/images/chapter15/si3_e.tex",
    "chars": 19,
    "preview": "\\int_{a}^{b} y\\, dx"
  },
  {
    "path": "docs/images/chapter15/si4_e.tex",
    "chars": 68,
    "preview": "( a + b ) ^{n} = \\sum_{i=0}^{n} \\frac {n!}{i! (n-i)!)} a^{i} b^{n-i}"
  },
  {
    "path": "docs/images/chapter15/si5_e.tex",
    "chars": 45,
    "preview": "(a+b)^{3} = b^{3} + 3ab^{2} + 3a^{2}b + a^{3}"
  },
  {
    "path": "docs/images/chapter15/si7_e.tex",
    "chars": 83,
    "preview": "\\sin{(x)},\n\\cos{\\left (x - \\frac {\\pi}{2} \\right ) },\n\\frac {e^{ix} - e^{-ix}} {2i}"
  },
  {
    "path": "docs/images/chapter16/fig-16-02.drawio",
    "chars": 1175,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-26T02:25:53.661Z\" agent=\"5.0 (Macintosh)\" etag=\"vHTPlASUrTs7OEF9AyXM\" "
  },
  {
    "path": "docs/images/chapter16/si1_e.tex",
    "chars": 172,
    "preview": "\\begin{tabular}{ll}\nA+B$-$AB; & A,B $>$ 0 \\\\\nA+B+AB;   & A,B $<$ 0 \\\\\n$\\dfrac {A + B} {1 - \\textup{min}( \\lvert A \\rvert"
  },
  {
    "path": "docs/images/chapter17/fig-17-01.drawio",
    "chars": 1137,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T09:02:00.240Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter17/fig-17-02.drawio",
    "chars": 1581,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T09:07:41.606Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter17/fig-17-03.drawio",
    "chars": 3717,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T10:21:28.582Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter17/fig-17-04.drawio",
    "chars": 2281,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T09:20:42.857Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter17/fig-17-07.drawio",
    "chars": 2999,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-26T02:17:40.335Z\" agent=\"5.0 (Macintosh)\" etag=\"oYByhiXs8627J6bAunMJ\" "
  },
  {
    "path": "docs/images/chapter17/fig-17-08.drawio",
    "chars": 1415,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-25T07:02:18.535Z\" agent=\"5.0 (Macintosh)\" etag=\"EjCUPBOif3cAYP1BI_4w\" "
  },
  {
    "path": "docs/images/chapter17/fig-17-09.drawio",
    "chars": 2047,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-25T07:15:21.767Z\" agent=\"5.0 (Macintosh)\" etag=\"u0zKqg2RZKcDchkyCD_N\" "
  },
  {
    "path": "docs/images/chapter17/fig-17-10.drawio",
    "chars": 1361,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T11:11:46.495Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter17/fig-17-11.drawio",
    "chars": 1967,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-25T07:20:44.922Z\" agent=\"5.0 (Macintosh)\" etag=\"hZo2cTFzl_uUeQSZQeDI\" "
  },
  {
    "path": "docs/images/chapter17/fig-17-12.drawio",
    "chars": 1805,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T06:55:01.992Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter18/diagram-18-01.drawio",
    "chars": 1129,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T07:24:57.841Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter18/diagram-18-02.drawio",
    "chars": 1917,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T07:29:18.146Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter18/diagram-18-03.drawio",
    "chars": 1977,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T07:31:15.506Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter18/diagram-18-04.drawio",
    "chars": 2013,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T07:32:40.601Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter18/diagram-18-05.drawio",
    "chars": 2181,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T08:04:51.086Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter18/fig-18-01.drawio",
    "chars": 2353,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T07:03:28.952Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter18/fig-18-02.drawio",
    "chars": 4249,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T07:13:33.961Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter18/fig-18-04.drawio",
    "chars": 2829,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-17T07:22:56.393Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter2/fig-02-01.drawio",
    "chars": 1461,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T06:33:09.104Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter3/fig-03-01.drawio",
    "chars": 1717,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-11T11:22:18.536Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter3/fig-03-02.drawio",
    "chars": 1293,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-07-14T14:24:16.276Z\" agent=\"5.0 (X11)\" etag=\"E-nha_KSy34UWql-ehKJ\" versio"
  },
  {
    "path": "docs/images/chapter3/fig-03-03.drawio",
    "chars": 1833,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-11T11:21:24.138Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter3/fig-03-04.drawio",
    "chars": 1937,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-11T11:40:00.697Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter4/diagram-04-01.drawio",
    "chars": 1473,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-11T11:59:07.788Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter4/diagram-04-02.drawio",
    "chars": 1123,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-24T09:23:39.974Z\" agent=\"5.0 (Macintosh)\" etag=\"apGPE0G1fcG2nx0sVERq\" "
  },
  {
    "path": "docs/images/chapter4/diagram-04-03.drawio",
    "chars": 1325,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T07:03:52.229Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter4/diagram-04-04.drawio",
    "chars": 1343,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-24T09:54:20.912Z\" agent=\"5.0 (Macintosh)\" etag=\"g5ymVWzsFlM_boXNuZB2\" "
  },
  {
    "path": "docs/images/chapter4/diagram-04-05.drawio",
    "chars": 1449,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T07:09:41.842Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter4/diagram-04-06.drawio",
    "chars": 1355,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-24T10:04:20.430Z\" agent=\"5.0 (Macintosh)\" etag=\"sdzarpRykyzf9gcCF3a9\" "
  },
  {
    "path": "docs/images/chapter4/diagram-04-09.drawio",
    "chars": 1355,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-24T10:30:56.397Z\" agent=\"5.0 (Macintosh)\" etag=\"VCByfXIIONK_C_gv-lhh\" "
  },
  {
    "path": "docs/images/chapter6/diagram-06-01.drawio",
    "chars": 1917,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T07:58:50.038Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter6/fig-06-01.drawio",
    "chars": 3359,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-26T03:54:02.344Z\" agent=\"5.0 (Macintosh)\" etag=\"P97z9yYVQUf-OvFriKdF\" "
  },
  {
    "path": "docs/images/chapter6/fig-06-02.drawio",
    "chars": 2951,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-03-26T03:58:05.698Z\" agent=\"5.0 (Macintosh)\" etag=\"s1-DpJLCAGxHsPcD4mhS\" "
  },
  {
    "path": "docs/images/chapter6/fig-06-03.drawio",
    "chars": 1413,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T07:38:13.449Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter6/fig-06-04.drawio",
    "chars": 1805,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T07:55:29.447Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter6/fig-06-05.drawio",
    "chars": 2917,
    "preview": "<mxfile host=\"app.diagrams.net\" modified=\"2022-02-15T08:15:14.672Z\" agent=\"5.0 (Macintosh; Intel Mac OS X 10_15_7) Apple"
  },
  {
    "path": "docs/images/chapter9/si1_e.tex",
    "chars": 30,
    "preview": "T_{n}=F_{n}\\frac{T_{i}}{F_{i}}"
  },
  {
    "path": "docs/images/chapter9/si2_e.tex",
    "chars": 21,
    "preview": "F_{n} \\alpha \\phi^{n}"
  },
  {
    "path": "docs/images/chapter9/si3_e.tex",
    "chars": 95,
    "preview": "T_{100} \\approx \\phi^{100}\\frac{1.1 \\text{sec}}{\\phi^{25}} \\approx 5 \\times 10^{15} \\text{sec}\n"
  },
  {
    "path": "docs/index.html",
    "chars": 1038,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Document</title>\n  <meta http-equiv=\"X-UA-Comp"
  },
  {
    "path": "docs/js/highlight-lisp.js",
    "chars": 25593,
    "preview": "/**\n * Common Lisp syntax highlighter\n *\n * @version 0.1.1\n * @author Andrew \"Danger\" Lyon\n * @copyright Lyon Bros. Ente"
  },
  {
    "path": "docs/markdown-help.md",
    "chars": 1975,
    "preview": "\n## Markdown help\n\n## Style guide\nTry to use Markdown instead of HTML. \nTry to do minimal changes from the text - don't "
  },
  {
    "path": "docs/preface.md",
    "chars": 26788,
    "preview": "# Preface\n\n> **paradigm** *n* **1** an example or pattern; *esp* an outstandingly clear or typical example.  \n> -*Longma"
  },
  {
    "path": "lisp/auxfns.lisp",
    "chars": 23783,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;; Code from Paradigms of AI Programming\n;;; Copyright (c) 1991 Peter Norvi"
  },
  {
    "path": "lisp/clos.lisp",
    "chars": 3085,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp;  -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrig"
  },
  {
    "path": "lisp/cmacsyma.lisp",
    "chars": 11518,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/compile1.lisp",
    "chars": 4914,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/compile2.lisp",
    "chars": 9226,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/compile3.lisp",
    "chars": 14295,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/compopt.lisp",
    "chars": 2206,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/edge-tab.lisp",
    "chars": 226,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/eliza-pm.lisp",
    "chars": 650,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/eliza.lisp",
    "chars": 6496,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/eliza1.lisp",
    "chars": 6026,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/examples.lisp",
    "chars": 69927,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991, 1996 Pe"
  },
  {
    "path": "lisp/gps-srch.lisp",
    "chars": 1213,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/gps.lisp",
    "chars": 8648,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/gps1.lisp",
    "chars": 2109,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/grammar.lisp",
    "chars": 17643,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter N"
  },
  {
    "path": "lisp/interp1.lisp",
    "chars": 6433,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/interp2.lisp",
    "chars": 2335,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/interp3.lisp",
    "chars": 3578,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/intro.lisp",
    "chars": 3330,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/krep.lisp",
    "chars": 9876,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp;  -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrig"
  },
  {
    "path": "lisp/krep1.lisp",
    "chars": 6001,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp;  -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrig"
  },
  {
    "path": "lisp/krep2.lisp",
    "chars": 5552,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp;  -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrig"
  },
  {
    "path": "lisp/lexicon.lisp",
    "chars": 6848,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter N"
  },
  {
    "path": "lisp/loop.lisp",
    "chars": 9800,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; Package: User; -*-\n\n#|| Examples of Loop expansion:\n\n(loop for i from 1 to n do"
  },
  {
    "path": "lisp/macsyma.lisp",
    "chars": 9895,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/macsymar.lisp",
    "chars": 3008,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/mycin-r.lisp",
    "chars": 2355,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/mycin.lisp",
    "chars": 14559,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/open-pdf.lisp",
    "chars": 641,
    "preview": "(defvar *paip-pdf-uri* \"https://github.com/norvig/paip-lisp/raw/master/\")\n\n(defun open-pdf (&optional (part 1))\n  (let* "
  },
  {
    "path": "lisp/othello.lisp",
    "chars": 16611,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/othello2.lisp",
    "chars": 14007,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/overview.lisp",
    "chars": 9300,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/patmatch.lisp",
    "chars": 6804,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/prolog.lisp",
    "chars": 4561,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/prolog1.lisp",
    "chars": 3735,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/prologc.lisp",
    "chars": 14509,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/prologc1.lisp",
    "chars": 5942,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/prologc2.lisp",
    "chars": 6878,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/prologcp.lisp",
    "chars": 4596,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/search.lisp",
    "chars": 11092,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/simple.lisp",
    "chars": 3810,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/student.lisp",
    "chars": 6932,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/syntax1.lisp",
    "chars": 4161,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/syntax2.lisp",
    "chars": 5661,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/syntax3.lisp",
    "chars": 8928,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "lisp/tutor.lisp",
    "chars": 6711,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;; Code for Paradigms of AI Programming\n;;; Copyright (c) 1996 Peter Norvig"
  },
  {
    "path": "lisp/unifgram.lisp",
    "chars": 6271,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter N"
  },
  {
    "path": "lisp/unify.lisp",
    "chars": 2142,
    "preview": ";;; -*- Mode: Lisp; Syntax: Common-Lisp; -*-\n;;; Code from Paradigms of Artificial Intelligence Programming\n;;; Copyrigh"
  },
  {
    "path": "lisp/waltz.lisp",
    "chars": 9495,
    "preview": ";;;; -*- Mode: Lisp; Syntax: Common-Lisp -*-\n;;;; Code from Paradigms of AI Programming\n;;;; Copyright (c) 1991 Peter No"
  },
  {
    "path": "meta/metadata.xml",
    "chars": 331,
    "preview": "<dc:title>Paradigms of Artificial Intelligence Programming</dc:title>\n<dc:language>en-GB</dc:language>\n<dc:creator opf:f"
  },
  {
    "path": "meta/stylesheet.css",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "meta/title.txt",
    "chars": 66,
    "preview": "% Paradigms of Artificial Intelligence Programming\n% Peter Norvig\n"
  },
  {
    "path": "paip.asd",
    "chars": 967,
    "preview": "(defpackage paip\n  (:use :cl)\n  (:shadow :defconstant)\n  (:export :requires :*paip-files* :do-examples :open-pdf))\n\n(in-"
  },
  {
    "path": "scripts/filter-ascii.rb",
    "chars": 2244,
    "preview": "#!/usr/bin/env ruby\n\n# switch non-ascii characters to ascii equivalents or html entities\n\n# references:\n# https://en.wik"
  },
  {
    "path": "scripts/httpd-py.sh",
    "chars": 35,
    "preview": "python2.6 -m SimpleHTTPServer 8000\n"
  },
  {
    "path": "scripts/httpd-rb.sh",
    "chars": 29,
    "preview": "ruby -run -e httpd . -p 8000\n"
  },
  {
    "path": "scripts/make-code-blocks.rb",
    "chars": 1100,
    "preview": "#!/usr/bin/env ruby\n\nrequire 'byebug'\n\ndebug = false\n# if true, won't emit non-code lines\n\ndef code?(str)\n  return false"
  },
  {
    "path": "scripts/make-epub.sh",
    "chars": 290,
    "preview": "pandoc \\\n  -o PAIP-alpha.epub \\\n  meta/title.txt \\\n  docs/{frontmatter.md,about.md,preface.md,chapter?.md,chapter??.md,a"
  },
  {
    "path": "scripts/make-pdf-from-epub.sh",
    "chars": 145,
    "preview": "#!/bin/bash\n\n# dependencies: calibre\n\nebook-convert PAIP-alpha.epub PAIP-alpha-calibre.pdf -v\n\n# this emits dozens of wa"
  },
  {
    "path": "scripts/markdown-to-text.sh",
    "chars": 367,
    "preview": "#!/bin/bash\n\n# turning the markdown into plaintext, for OCR comparisons\n# results: sentence per line, for nicer diffs\n\nO"
  },
  {
    "path": "scripts/one-offs/add-page-anchors.rb",
    "chars": 610,
    "preview": "#!/usr/bin/env ruby\n\nin_path = \"PAIP.txt\"\nout_path = \"PAIP.txt.markers\"\n\nchapter = 0\nin_file = File.open(in_path, \"r\").r"
  },
  {
    "path": "scripts/one-offs/linkify_page_numbers.rb",
    "chars": 1034,
    "preview": "#!/usr/bin/env ruby\n\nrequire \"byebug\"\n\nin_path = \"PAIP.txt\"\nout_path = \"PAIP.txt.linkify\"\n\ndef parse_chapter_file(line)\n"
  },
  {
    "path": "scripts/prepare-for-merge.rb",
    "chars": 614,
    "preview": "#!/usr/bin/env ruby\n\nrequire \"byebug\"\nchap_path = ARGV.first || \"docs/chapter10.md\"\nout_path = \"#{chap_path}.merge\"\n\ncha"
  },
  {
    "path": "scripts/split-chapters-markdown.rb",
    "chars": 728,
    "preview": "#!/usr/bin/env ruby\n\n# require \"byebug\"\n\nin_path = \"PAIP-safari.md\"\nout_path = \"docs\"\n\nin_file = File.open(in_path, \"r\")"
  },
  {
    "path": "scripts/split-chapters.rb",
    "chars": 730,
    "preview": "#!/usr/bin/env ruby\n\n# require \"byebug\"\nin_path = \"PAIP.txt\"\nout_path = \"docs\"\n\nin_file = File.open(in_path, \"r\").read\no"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the norvig/paip-lisp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 163 files (5.9 MB), approximately 1.6M tokens, and a symbol index with 4 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!