You are on page 1of 314

An Introdu

tion to
Programming in Ema s Lisp
An Introdu tion to
Programming in Ema s Lisp
Se ond Edition

by Robert J. Chassell
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 2001, 2002 Free
Software Foundation, In .

Published by the Free Software Foundation, In .


59 Temple Pla e, Suite 330
Boston, MA 02111-1307 USA

Edition 2.05, 2001 Jan 5


ISBN 1-882114-43-4
Permission is granted to opy, distribute and/or modify this do ument under
the terms of the GNU Free Do umentation Li ense, Version 1.1 or any later
version published by the Free Software Foundation; there being no Invariant
Se tion, with the Front-Cover Texts being \A GNU Manual", and with the
Ba k-Cover Texts as in (a) below. A opy of the li ense is in luded in the
se tion entitled \GNU Free Do umentation Li ense".
(a) The FSF's Ba k-Cover Text is: \You have freedom to opy and modify
this GNU Manual, like GNU software. Copies published by the Free Software
Foundation raise funds for GNU development."
i

Short Contents
Prefa e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
1 List Pro essing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2 Pra ti ing Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3 How To Write Fun tion De nitions . . . . . . . . . . . . . . . . . . 29
4 A Few Bu er{Related Fun tions . . . . . . . . . . . . . . . . . . . . 51
5 A Few More Complex Fun tions . . . . . . . . . . . . . . . . . . . . 63
6 Narrowing and Widening . . . . . . . . . . . . . . . . . . . . . . . . . 77
7 ar, dr, ons: Fundamental Fun tions . . . . . . . . . . . . . 81
8 Cutting and Storing Text . . . . . . . . . . . . . . . . . . . . . . . . . 89
9 How Lists are Implemented . . . . . . . . . . . . . . . . . . . . . . . 113
10 Yanking Text Ba k . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
11 Loops and Re ursion . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
12 Regular Expression Sear hes . . . . . . . . . . . . . . . . . . . . . . 149
13 Counting: Repetition and Regexps . . . . . . . . . . . . . . . . . . 167
14 Counting Words in a defun . . . . . . . . . . . . . . . . . . . . . . 181
15 Readying a Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
16 Your `.ema s' File . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
17 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
18 Con lusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Appendix A The the-the Fun tion . . . . . . . . . . . . . . . . . . 241
Appendix B Handling the Kill Ring . . . . . . . . . . . . . . . . . . . 243
Appendix C A Graph with Labelled Axes . . . . . . . . . . . . . . . 255
Appendix D GNU Free Do umentation Li ense . . . . . . . . . . . 279
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
ii
iii

Table of Contents
Prefa e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
On Reading this Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
For Whom This is Written . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xii
Lisp History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
A Note for Novi es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
Thank You . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv

1 List Pro essing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1


1.1 Lisp Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Lisp Atoms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.2 Whitespa e in Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.3 GNU Ema s Helps You Type Lists . . . . . . . . . . . . . . . 3
1.2 Run a Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Generate an Error Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4 Symbol Names and Fun tion De nitions . . . . . . . . . . . . . . . . . . 6
1.5 The Lisp Interpreter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.5.1 Byte Compiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6 Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6.1 Evaluating Inner Lists . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.7 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.7.1 Error Message for a Symbol Without a Fun tion . . 11
1.7.2 Error Message for a Symbol Without a Value . . . . 11
1.8 Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.8.1 Arguments' Data Types . . . . . . . . . . . . . . . . . . . . . . . . 13
1.8.2 An Argument as the Value of a Variable or List . . 13
1.8.3 Variable Number of Arguments . . . . . . . . . . . . . . . . . 14
1.8.4 Using the Wrong Type Obje t as an Argument . . 14
1.8.5 The message Fun tion . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.9 Setting the Value of a Variable . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.9.1 Using set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.9.2 Using setq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.9.3 Counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.10 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.11 Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2 Pra ti ing Evaluation . . . . . . . . . . . . . . . . . . . . . 23


2.1 Bu er Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.2 Getting Bu ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.3 Swit hing Bu ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.4 Bu er Size and the Lo ation of Point . . . . . . . . . . . . . . . . . . . . 27
2.5 Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
iv
3 How To Write Fun tion De nitions . . . . . . . . 29
3.1 The defun Spe ial Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.2 Install a Fun tion De nition . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.2.1 Change a Fun tion De nition . . . . . . . . . . . . . . . . . . . 32
3.3 Make a Fun tion Intera tive . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.3.1 An Intera tive multiply-by-seven . . . . . . . . . . . . . 34
3.4 Di erent Options for intera tive . . . . . . . . . . . . . . . . . . . . . . 35
3.5 Install Code Permanently . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.6 let . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.6.1 The Parts of a let Expression . . . . . . . . . . . . . . . . . . 37
3.6.2 Sample let Expression . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.6.3 Uninitialized Variables in a let Statement . . . . . . . 39
3.7 The if Spe ial Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.7.1 The type-of-animal Fun tion in Detail . . . . . . . . . 41
3.8 If{then{else Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.9 Truth and Falsehood in Ema s Lisp . . . . . . . . . . . . . . . . . . . . . 43
3.10 save-ex ursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.10.1 Template for a save-ex ursion Expression . . . . 45
3.11 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.12 Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

4 A Few Bu er{Related Fun tions . . . . . . . . . . . 51


4.1 Finding More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.2 A Simpli ed beginning-of-buffer De nition . . . . . . . . . . . . 52
4.3 The De nition of mark-whole-buffer . . . . . . . . . . . . . . . . . . . 54
4.3.1 Body of mark-whole-buffer .. . . . . . . . . . . . . . . . . . 55
4.4 The De nition of append-to-buffer . . . . . . . . . . . . . . . . . . . . 56
4.4.1 The append-to-buffer Intera tive Expression . . . 57
4.4.2 The Body of append-to-buffer . . . . . . . . . . . . . . . . 57
4.4.3 save-ex ursion in append-to-buffer . . . . . . . . . . 58
4.5 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.6 Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
v
5 A Few More Complex Fun tions . . . . . . . . . . . 63
5.1 The De nition of opy-to-buffer . . . . . . . . . . . . . . . . . . . . . . . 63
5.2 The De nition of insert-buffer . . . . . . . . . . . . . . . . . . . . . . . . 64
5.2.1 The Intera tive Expression in insert-buffer . . . . 65
A Read-only Bu er . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
`b' in an Intera tive Expression . . . . . . . . . . . . . . . . . 65
5.2.2 The Body of the insert-buffer Fun tion . . . . . . . 65
5.2.3 insert-buffer With an if Instead of an or . . . . . 66
5.2.4 The or in the Body . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.2.5 The let Expression in insert-buffer . . . . . . . . . . 68
5.3 Complete De nition of beginning-of-buffer .. . . . . . . . . . . 69
5.3.1 Optional Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.3.2 beginning-of-buffer with an Argument . . . . . . . 71
What happens in a large bu er . . . . . . . . . . . . . . . . . 71
What happens in a small bu er . . . . . . . . . . . . . . . . 72
5.3.3 The Complete beginning-of-buffer .. . . . . . . . . . 73
5.4 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
5.5 optional Argument Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

6 Narrowing and Widening . . . . . . . . . . . . . . . . . . 77


6.1 The save-restri tion Spe ial Form . . . . . . . . . . . . . . . . . . . . 77
6.2 what-line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.3 Exer ise with Narrowing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

7 ar, dr, ons: Fundamental Fun tions . . . . . 81


7.1 ar and dr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.2 ons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
7.2.1 Find the Length of a List: length . . . . . . . . . . . . . . 84
7.3 nth dr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
7.4 nth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7.5 set ar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
7.6 set dr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
7.7 Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
vi
8 Cutting and Storing Text . . . . . . . . . . . . . . . . . 89
8.1 zap-to- har . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.1.1 The intera tive Expression . . . . . . . . . . . . . . . . . . . 90
8.1.2 The Body of zap-to- har . . . . . . . . . . . . . . . . . . . . . . 91
8.1.3 The sear h-forward Fun tion . . . . . . . . . . . . . . . . . 92
8.1.4 The progn Spe ial Form . . . . . . . . . . . . . . . . . . . . . . . 93
8.1.5 Summing up zap-to- har . . . . . . . . . . . . . . . . . . . . . 93
8.2 kill-region . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
8.2.1 ondition- ase .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
8.2.2 delete-and-extra t-region . . . . . . . . . . . . . . . . . . 96
8.3 delete-and-extra t-region: Digressing into C . . . . . . . . . 98
8.4 Initializing a Variable with defvar . . . . . . . . . . . . . . . . . . . . . 100
8.4.1 defvar and an asterisk . . . . . . . . . . . . . . . . . . . . . . . . 101
8.5 opy-region-as-kill .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
8.5.1 The Body of opy-region-as-kill .. . . . . . . . . . . 103
The kill-append fun tion . . . . . . . . . . . . . . . . . . . . 104
The kill-new fun tion . . . . . . . . . . . . . . . . . . . . . . . 105
8.6 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
8.7 Sear hing Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

9 How Lists are Implemented . . . . . . . . . . . . . . 113


9.1 Symbols as a Chest of Drawers . . . . . . . . . . . . . . . . . . . . . . . . . 115
9.2 Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

10 Yanking Text Ba k . . . . . . . . . . . . . . . . . . . . . 117


10.1 Kill Ring Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
10.2 The kill-ring-yank-pointer Variable . . . . . . . . . . . . . . . 117
10.3 Exer ises with yank and nth dr . . . . . . . . . . . . . . . . . . . . . . . 119

11 Loops and Re ursion . . . . . . . . . . . . . . . . . . . . 121


11.1 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
11.1.1 A while Loop and a List . . . . . . . . . . . . . . . . . . . . . 122
11.1.2 An Example: print-elements-of-list . . . . . . 123
11.1.3 A Loop with an In rementing Counter . . . . . . . . 124
Example with in rementing ounter . . . . . . . . . . . 125
The parts of the fun tion de nition . . . . . . . . . . . . 126
Putting the fun tion de nition together . . . . . . . . 127
11.1.4 Loop with a De rementing Counter . . . . . . . . . . . 129
Example with de rementing ounter . . . . . . . . . . . 129
The parts of the fun tion de nition . . . . . . . . . . . . 130
Putting the fun tion de nition together . . . . . . . . 130
11.2 Save your time: dolist and dotimes . . . . . . . . . . . . . . . . . . 131
The dolist Ma ro . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
The dotimes Ma ro . . . . . . . . . . . . . . . . . . . . . . . . . . 133
vii
11.3 Re ursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
11.3.1 Building Robots: Extending the Metaphor . . . . . 134
11.3.2 The Parts of a Re ursive De nition . . . . . . . . . . . 135
11.3.3 Re ursion with a List . . . . . . . . . . . . . . . . . . . . . . . . 136
11.3.4 Re ursion in Pla e of a Counter . . . . . . . . . . . . . . 137
An argument of 3 or 4 . . . . . . . . . . . . . . . . . . . . . . . . 138
11.3.5 Re ursion Example Using ond . . . . . . . . . . . . . . . 139
11.3.6 Re ursive Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Re ursive Pattern: every . . . . . . . . . . . . . . . . . . . . . 141
Re ursive Pattern: a umulate . . . . . . . . . . . . . . . . 142
Re ursive Pattern: keep . . . . . . . . . . . . . . . . . . . . . . 143
11.3.7 Re ursion without Deferments . . . . . . . . . . . . . . . . 143
11.3.8 No Deferment Solution . . . . . . . . . . . . . . . . . . . . . . . 145
11.4 Looping Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

12 Regular Expression Sear hes . . . . . . . . . . . . 149


12.1 The Regular Expression for senten e-end . . . . . . . . . . . . . 149
12.2 The re-sear h-forward Fun tion . . . . . . . . . . . . . . . . . . . . . 150
12.3 forward-senten e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
The while loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
The regular expression sear h . . . . . . . . . . . . . . . . . . . . . . . . 154
12.4 forward-paragraph: a Goldmine of Fun tions . . . . . . . . . 155
The let* expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
The forward motion while loop . . . . . . . . . . . . . . . . . . . . . . 158
Between paragraphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Within paragraphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
No ll pre x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
With a ll pre x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
12.5 Create Your Own `TAGS' File . . . . . . . . . . . . . . . . . . . . . . . . . . 163
12.6 Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
12.7 Exer ises with re-sear h-forward . . . . . . . . . . . . . . . . . . . . 166

13 Counting: Repetition and Regexps . . . . . . 167


13.1 The ount-words-region Fun tion . . . . . . . . . . . . . . . . . . . 167
13.1.1 The Whitespa e Bug in ount-words-region . . 170
13.2 Count Words Re ursively . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
13.3 Exer ise: Counting Pun tuation . . . . . . . . . . . . . . . . . . . . . . . 179
viii
14 Counting Words in a defun . . . . . . . . . . . . . . 181
14.1 What to Count? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
14.2 What Constitutes a Word or Symbol? . . . . . . . . . . . . . . . . . 182
14.3 The ount-words-in-defun Fun tion . . . . . . . . . . . . . . . . . 183
14.4 Count Several defuns Within a File . . . . . . . . . . . . . . . . . . . 186
14.5 Find a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
14.6 lengths-list-file in Detail . . . . . . . . . . . . . . . . . . . . . . . . . 188
14.7 Count Words in defuns in Di erent Files . . . . . . . . . . . . . . 190
14.7.1 The append Fun tion . . . . . . . . . . . . . . . . . . . . . . . . 191
14.8 Re ursively Count Words in Di erent Files . . . . . . . . . . . . . 192
14.9 Prepare the Data for Display in a Graph . . . . . . . . . . . . . . . 193
14.9.1 Sorting Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
14.9.2 Making a List of Files . . . . . . . . . . . . . . . . . . . . . . . . 194
14.9.3 Counting fun tion de nitions . . . . . . . . . . . . . . . . . 197

15 Readying a Graph . . . . . . . . . . . . . . . . . . . . . . 203


15.1 The graph-body-print Fun tion . . . . . . . . . . . . . . . . . . . . . . 208
15.2 The re ursive-graph-body-print Fun tion . . . . . . . . . . . 210
15.3 Need for Printed Axes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
15.4 Exer ise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212

16 Your `.ema s' File . . . . . . . . . . . . . . . . . . . . . . . 213


16.1 Site-wide Initialization Files . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
16.2 Spe ifying Variables using def ustom . . . . . . . . . . . . . . . . . . 214
16.3 Beginning a `.ema s' File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
16.4 Text and Auto Fill Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
16.5 Mail Aliases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
16.6 Indent Tabs Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
16.7 Some Keybindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
16.8 Keymaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
16.9 Loading Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
16.10 Autoloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
16.11 A Simple Extension: line-to-top-of-window . . . . . . . . 224
16.12 X11 Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
16.13 Mis ellaneous Settings for a `.ema s' File . . . . . . . . . . . . . 227
16.14 A Modi ed Mode Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228

17 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
17.1 231
debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17.2 debug-on-entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .232
17.3 debug-on-quit and (debug) . . . . . . . . . . . . . . . . . . . . . . . . . . 234
17.4 The edebug Sour e Level Debugger . . . . . . . . . . . . . . . . . . . . 235
17.5 Debugging Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
ix
18 Con lusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Appendix A The the-the Fun tion . . . . . . . . . . 241
Appendix B Handling the Kill Ring . . . . . . . . 243
B.1 The rotate-yank-pointer Fun tion . . . . . . . . . . . . . . . . . . . 243
B.1.1 The Body of rotate-yank-pointer .. . . . . . . . . . 244
The else-part of the if expression . . . . . . . . . . . . . 245
The % remainder fun tion . . . . . . . . . . . . . . . . . . . . . 247
Using % in rotate-yank-pointer . . . . . . . . . . . . . 248
Pointing to the last element . . . . . . . . . . . . . . . . . . . 248
B.2 yank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Passing the argument . . . . . . . . . . . . . . . . . . . . . . . . 250
Passing a negative argument . . . . . . . . . . . . . . . . . . 251
B.3 yank-pop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252

Appendix C A Graph with Labelled Axes . . . 255


C.1 The print-graph Varlist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
C.2 The print-Y-axis Fun tion . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
C.2.1 Side Trip: Compute a Remainder . . . . . . . . . . . . . . 258
C.2.2 Constru t a Y Axis Element . . . . . . . . . . . . . . . . . . 259
C.2.3 Create a Y Axis Column . . . . . . . . . . . . . . . . . . . . . . 261
C.2.4 The Not Quite Final Version of print-Y-axis . . 262
C.3 The print-X-axis Fun tion . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
C.3.1 X Axis Ti Marks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
C.4 Printing the Whole Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
C.4.1 Testing print-graph . . . . . . . . . . . . . . . . . . . . . . . . . 270
C.4.2 Graphing Numbers of Words and Symbols . . . . . 271
C.4.3 A lambda Expression: Useful Anonymity . . . . . . . 272
C.4.4 The map ar Fun tion . . . . . . . . . . . . . . . . . . . . . . . . . 274
C.4.5 Another Bug . . . Most Insidious . . . . . . . . . . . . . . 274
C.4.6 The Printed Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

Appendix D GNU Free Do umentation Li ense


. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
x
On Reading this Text xi

Prefa e
Most of the GNU Ema s integrated environment is written in the pro-
gramming language alled Ema s Lisp. The ode written in this program-
ming language is the software|the sets of instru tions|that tell the om-
puter what to do when you give it ommands. Ema s is designed so that
you an write new ode in Ema s Lisp and easily install it as an extension
to the editor.
(GNU Ema s is sometimes alled an \extensible editor", but it does mu h
more than provide editing apabilities. It is better to refer to Ema s as
an \extensible omputing environment". However, that phrase is quite a
mouthful. It is easier to refer to Ema s simply as an editor. Moreover,
everything you do in Ema s| nd the Mayan date and phases of the moon,
simplify polynomials, debug ode, manage les, read letters, write books|all
these a tivities are kinds of editing in the most general sense of the word.)
Although Ema s Lisp is usually thought of in asso iation only with
Ema s, it is a full omputer programming language. You an use Ema s
Lisp as you would any other programming language.
Perhaps you want to understand programming; perhaps you want to ex-
tend Ema s; or perhaps you want to be ome a programmer. This introdu -
tion to Ema s Lisp is designed to get you started: to guide you in learning
the fundamentals of programming, and more importantly, to show you how
you an tea h yourself to go further.

On Reading this Text


All through this do ument, you will see little sample programs you an
run inside of Ema s. If you read this do ument in Info inside of GNU
Ema s, you an run the programs as they appear. (This is easy to do and
is explained when the examples are presented.) Alternatively, you an read
this introdu tion as a printed book while sitting beside a omputer running
Ema s. (This is what I like to do; I like printed books.) If you don't have a
running Ema s beside you, you an still read this book, but in this ase, it
is best to treat it as a novel or as a travel guide to a ountry not yet visited:
interesting, but not the same as being there.
Mu h of this introdu tion is dedi ated to walk-throughs or guided tours
of ode used in GNU Ema s. These tours are designed for two purposes:
rst, to give you familiarity with real, working ode ( ode you use every
day); and, se ond, to give you familiarity with the way Ema s works. It is
interesting to see how a working environment is implemented. Also, I hope
that you will pi k up the habit of browsing through sour e ode. You an
learn from it and mine it for ideas. Having GNU Ema s is like having a
dragon's ave of treasures.
In addition to learning about Ema s as an editor and Ema s Lisp as
a programming language, the examples and guided tours will give you an
xii Prefa e

opportunity to get a quainted with Ema s as a Lisp programming environ-


ment. GNU Ema s supports programming and provides tools that you will
want to be ome omfortable using, su h as M-. (the key whi h invokes the
find-tag ommand). You will also learn about bu ers and other obje ts
that are part of the environment. Learning about these features of Ema s is
like learning new routes around your home town.
Finally, I hope to onvey some of the skills for using Ema s to learn
aspe ts of programming that you don't know. You an often use Ema s to
help you understand what puzzles you or to nd out how to do something
new. This self-relian e is not only a pleasure, but an advantage.

For Whom This is Written


This text is written as an elementary introdu tion for people who are not
programmers. If you are a programmer, you may not be satis ed with this
primer. The reason is that you may have be ome expert at reading referen e
manuals and be put o by the way this text is organized.
An expert programmer who reviewed this text said to me:
I prefer to learn from referen e manuals. I \dive into" ea h para-
graph, and \ ome up for air" between paragraphs.
When I get to the end of a paragraph, I assume that that subje t
is done, nished, that I know everything I need (with the possible
ex eption of the ase when the next paragraph starts talking about
it in more detail). I expe t that a well written referen e manual
will not have a lot of redundan y, and that it will have ex ellent
pointers to the (one) pla e where the information I want is.
This introdu tion is not written for this person!
Firstly, I try to say everything at least three times: rst, to introdu e it;
se ond, to show it in ontext; and third, to show it in a di erent ontext, or
to review it.
Se ondly, I hardly ever put all the information about a subje t in one
pla e, mu h less in one paragraph. To my way of thinking, that imposes
too heavy a burden on the reader. Instead I try to explain only what you
need to know at the time. (Sometimes I in lude a little extra information
so you won't be surprised later when the additional information is formally
introdu ed.)
When you read this text, you are not expe ted to learn everything the rst
time. Frequently, you need only make, as it were, a `nodding a quaintan e'
with some of the items mentioned. My hope is that I have stru tured the
text and given you enough hints that you will be alert to what is important,
and on entrate on it.
You will need to \dive into" some paragraphs; there is no other way to
read them. But I have tried to keep down the number of su h paragraphs.
A Note for Novi es xiii

This book is intended as an approa hable hill, rather than as a daunting


mountain.
This introdu tion to Programming in Ema s Lisp has a ompanion do -
ument, The GNU Ema s Lisp Referen e Manual. The referen e manual has
more detail than this introdu tion. In the referen e manual, all the infor-
mation about one topi is on entrated in one pla e. You should turn to it
if you are like the programmer quoted above. And, of ourse, after you have
read this Introdu tion, you will nd the Referen e Manual useful when you
are writing your own programs.

Lisp History
Lisp was rst developed in the late 1950s at the Massa husetts Institute
of Te hnology for resear h in arti ial intelligen e. The great power of the
Lisp language makes it superior for other purposes as well, su h as writing
editor ommands and integrated environments.
GNU Ema s Lisp is largely inspired by Ma lisp, whi h was written at
MIT in the 1960s. It is somewhat inspired by Common Lisp, whi h be ame
a standard in the 1980s. However, Ema s Lisp is mu h simpler than Common
Lisp. (The standard Ema s distribution ontains an optional extensions le,
` l.el', that adds many Common Lisp features to Ema s Lisp.)

A Note for Novi es


If you don't know GNU Ema s, you an still read this do ument prof-
itably. However, I re ommend you learn Ema s, if only to learn to move
around your omputer s reen. You an tea h yourself how to use Ema s
with the on-line tutorial. To use it, type C-h t. (This means you press and
release the hCTRLi key and the h at the same time, and then press and release
t.)
Also, I often refer to one of Ema s' standard ommands by listing the
keys whi h you press to invoke the ommand and then giving the name of
the ommand in parentheses, like this: M-C-\ (indent-region). What this
means is that the indent-region ommand is ustomarily invoked by typing
M-C-\. (You an, if you wish, hange the keys that are typed to invoke the
ommand; this is alled rebinding. See Se tion 16.8, \Keymaps", page 221.)
The abbreviation M-C-\ means that you type your hMETAi key, hCTRLi key
and h\i key all at the same time. (On many modern keyboards the hMETAi
key is labelled hALTi.) Sometimes a ombination like this is alled a key hord,
sin e it is similar to the way you play a hord on a piano. If your keyboard
does not have a hMETAi key, the hESCi key pre x is used in pla e of it. In
this ase, M-C-\ means that you press and release your hESCi key and then
type the hCTRLi key and the h\i key at the same time. But usually M-C-\
means press the hCTRLi key along with the key that is labelled hALTi and, at
the same time, press the h\i key.
xiv Prefa e

In addition to typing a lone key hord, you an pre x what you type with
C-u, whi h is alled the `universal argument'. The C-u key hord passes an
argument to the subsequent ommand. Thus, to indent a region of plain
text by 6 spa es, mark the region, and then type C-u 6 M-C-\. (If you do
not spe ify a number, Ema s either passes the number 4 to the ommand
or otherwise runs the ommand di erently than it would otherwise.) See
se tion \Numeri Arguments" in The GNU Ema s Manual.
If you are reading this in Info using GNU Ema s, you an read through
this whole do ument just by pressing the spa e bar, hSPCi. (To learn about
Info, type C-h i and then sele t Info.)
A note on terminology: when I use the word Lisp alone, I often am
referring to the various diale ts of Lisp in general, but when I speak of
Ema s Lisp, I am referring to GNU Ema s Lisp in parti ular.

Thank You
My thanks to all who helped me with this book. My espe ial thanks to
Jim Blandy, Noah Friedman, Jim Kingdon, Roland M Grath, Frank Ritter,
Randy Smith, Ri hard M. Stallman, and Melissa Weisshaus. My thanks
also go to both Philip Johnson and David Stampe for their patient en our-
agement. My mistakes are my own.
Robert J. Chassell
Lisp Atoms 1

1 List Pro essing


To the untutored eye, Lisp is a strange programming language. In Lisp
ode there are parentheses everywhere. Some people even laim that the
name stands for `Lots of Isolated Silly Parentheses'. But the laim is un-
warranted. Lisp stands for LISt Pro essing, and the programming language
handles lists (and lists of lists) by putting them between parentheses. The
parentheses mark the boundaries of the list. Sometimes a list is pre eded by
a single apostrophe or quotation mark, `''. Lists are the basis of Lisp.

1.1 Lisp Lists


In Lisp, a list looks like this: '(rose violet daisy butter up). This
list is pre eded by a single apostrophe. It ould just as well be written as
follows, whi h looks more like the kind of list you are likely to be familiar
with:
'(rose
violet
daisy
butter up)
The elements of this list are the names of the four di erent owers, separated
from ea h other by whitespa e and surrounded by parentheses, like owers
in a eld with a stone wall around them.
Lists an also have numbers in them, as in this list: (+ 2 2). This list
has a plus-sign, `+', followed by two `2's, ea h separated by whitespa e.
In Lisp, both data and programs are represented the same way; that is,
they are both lists of words, numbers, or other lists, separated by white-
spa e and surrounded by parentheses. (Sin e a program looks like data, one
program may easily serve as data for another; this is a very powerful feature
of Lisp.) (In identally, these two parentheti al remarks are not Lisp lists,
be ause they ontain `;' and `.' as pun tuation marks.)
Here is another list, this time with a list inside of it:
'(this list has (a list inside of it))
The omponents of this list are the words `this', `list', `has', and the
list `(a list inside of it)'. The interior list is made up of the words `a',
`list', `inside', `of', `it'.

1.1.1 Lisp Atoms


In Lisp, what we have been alling words are alled atoms. This term
omes from the histori al meaning of the word atom, whi h means `indivis-
ible'. As far as Lisp is on erned, the words we have been using in the lists
annot be divided into any smaller parts and still mean the same thing as
part of a program; likewise with numbers and single hara ter symbols like
2 Chapter 1: List Pro essing

`+'. On the other hand, unlike an atom, a list an be split into parts. (See
Chapter 7, \ ar dr & ons Fundamental Fun tions", page 81.)

In a list, atoms are separated from ea h other by whitespa e. They an


be right next to a parenthesis.

Te hni ally speaking, a list in Lisp onsists of parentheses surrounding


atoms separated by whitespa e or surrounding other lists or surrounding
both atoms and other lists. A list an have just one atom in it or have
nothing in it at all. A list with nothing in it looks like this: (), and is alled
the empty list. Unlike anything else, an empty list is onsidered both an
atom and a list at the same time.

The printed representation of both atoms and lists are alled symboli
expressions or, more on isely, s-expressions. The word expression by itself
an refer to either the printed representation, or to the atom or list as it
is held internally in the omputer. Often, people use the term expression
indis riminately. (Also, in many texts, the word form is used as a synonym
for expression.)

In identally, the atoms that make up our universe were named su h when
they were thought to be indivisible; but it has been found that physi al atoms
are not indivisible. Parts an split o an atom or it an ssion into two parts
of roughly equal size. Physi al atoms were named prematurely, before their
truer nature was found. In Lisp, ertain kinds of atom, su h as an array, an
be separated into parts; but the me hanism for doing this is di erent from
the me hanism for splitting a list. As far as list operations are on erned,
the atoms of a list are unsplittable.

As in English, the meanings of the omponent letters of a Lisp atom are


di erent from the meaning the letters make as a word. For example, the
word for the South Ameri an sloth, the `ai', is ompletely di erent from the
two words, `a', and `i'.

There are many kinds of atom in nature but only a few in Lisp: for
example, numbers, su h as 37, 511, or 1729, and symbols, su h as `+', `foo',
or `forward-line'. The words we have listed in the examples above are
all symbols. In everyday Lisp onversation, the word \atom" is not often
used, be ause programmers usually try to be more spe i about what kind
of atom they are dealing with. Lisp programming is mostly about symbols
(and sometimes numbers) within lists. (In identally, the pre eding three
word parentheti al remark is a proper list in Lisp, sin e it onsists of atoms,
whi h in this ase are symbols, separated by whitespa e and en losed by
parentheses, without any non-Lisp pun tuation.)
GNU Ema s Helps You Type Lists 3

In addition, text between double quotation marks|even senten es or


paragraphs|is an atom. Here is an example:
'(this list in ludes "text between quotation marks.")
In Lisp, all of the quoted text in luding the pun tuation mark and the blank
spa es is a single atom. This kind of atom is alled a string (for `string
of hara ters') and is the sort of thing that is used for messages that a
omputer an print for a human to read. Strings are a di erent kind of atom
than numbers or symbols and are used di erently.

1.1.2 Whitespa e in Lists


The amount of whitespa e in a list does not matter. From the point of
view of the Lisp language,
'(this list
looks like this)
is exa tly the same as this:
'(this list looks like this)
Both examples show what to Lisp is the same list, the list made up of
the symbols `this', `list', `looks', `like', and `this' in that order.
Extra whitespa e and newlines are designed to make a list more readable
by humans. When Lisp reads the expression, it gets rid of all the extra
whitespa e (but it needs to have at least one spa e between atoms in order
to tell them apart.)
Odd as it seems, the examples we have seen over almost all of what
Lisp lists look like! Every other list in Lisp looks more or less like one of
these examples, ex ept that the list may be longer and more omplex. In
brief, a list is between parentheses, a string is between quotation marks, a
symbol looks like a word, and a number looks like a number. (For ertain
situations, square bra kets, dots and a few other spe ial hara ters may be
used; however, we will go quite far without them.)

1.1.3 GNU Ema s Helps You Type Lists


When you type a Lisp expression in GNU Ema s using either Lisp Intera -
tion mode or Ema s Lisp mode, you have available to you several ommands
to format the Lisp expression so it is easy to read. For example, pressing
the hTABi key automati ally indents the line the ursor is on by the right
amount. A ommand to properly indent the ode in a region is ustomarily
bound to M-C-\. Indentation is designed so that you an see whi h elements
of a list belongs to whi h list|elements of a sub-list are indented more than
the elements of the en losing list.
In addition, when you type a losing parenthesis, Ema s momentarily
jumps the ursor ba k to the mat hing opening parenthesis, so you an see
whi h one it is. This is very useful, sin e every list you type in Lisp must have
4 Chapter 1: List Pro essing

its losing parenthesis mat h its opening parenthesis. (See se tion \Major
Modes" in The GNU Ema s Manual, for more information about Ema s'
modes.)

1.2 Run a Program


A list in Lisp|any list|is a program ready to run. If you run it (for
whi h the Lisp jargon is evaluate), the omputer will do one of three things:
do nothing ex ept return to you the list itself; send you an error message; or,
treat the rst symbol in the list as a ommand to do something. (Usually,
of ourse, it is the last of these three things that you really want!)
The single apostrophe, ', that I put in front of some of the example lists
in pre eding se tions is alled a quote; when it pre edes a list, it tells Lisp
to do nothing with the list, other than take it as it is written. But if there is
no quote pre eding a list, the rst item of the list is spe ial: it is a ommand
for the omputer to obey. (In Lisp, these ommands are alled fun tions.)
The list (+ 2 2) shown above did not have a quote in front of it, so Lisp
understands that the + is an instru tion to do something with the rest of the
list: add the numbers that follow.
If you are reading this inside of GNU Ema s in Info, here is how you
an evaluate su h a list: pla e your ursor immediately after the right hand
parenthesis of the following list and then type C-x C-e:
(+ 2 2)
You will see the number 4 appear in the e ho area. (In the jargon, what you
have just done is \evaluate the list." The e ho area is the line at the bottom
of the s reen that displays or \e hoes" text.) Now try the same thing with a
quoted list: pla e the ursor right after the following list and type C-x C-e:
'(this is a quoted list)
You will see (this is a quoted list) appear in the e ho area.
In both ases, what you are doing is giving a ommand to the program
inside of GNU Ema s alled the Lisp interpreter|giving the interpreter a
ommand to evaluate the expression. The name of the Lisp interpreter omes
from the word for the task done by a human who omes up with the meaning
of an expression|who \interprets" it.
You an also evaluate an atom that is not part of a list|one that is not
surrounded by parentheses; again, the Lisp interpreter translates from the
humanly readable expression to the language of the omputer. But before
dis ussing this (see Se tion 1.7, \Variables", page 10), we will dis uss what
the Lisp interpreter does when you make an error.

1.3 Generate an Error Message


Partly so you won't worry if you do it a identally, we will now give a
ommand to the Lisp interpreter that generates an error message. This is a
Generate an Error Message 5

harmless a tivity; and indeed, we will often try to generate error messages
intentionally. On e you understand the jargon, error messages an be in-
formative. Instead of being alled \error" messages, they should be alled
\help" messages. They are like signposts to a traveller in a strange ountry;
de iphering them an be hard, but on e understood, they an point the way.
The error message is generated by a built-in GNU Ema s debugger. We
will `enter the debugger'. You get out of the debugger by typing q.
What we will do is evaluate a list that is not quoted and does not have
a meaningful ommand as its rst element. Here is a list almost exa tly the
same as the one we just used, but without the single-quote in front of it.
Position the ursor right after it and type C-x C-e:
(this is an unquoted list)
What you see depends on whi h version of Ema s you are running. GNU
Ema s version 21 provides more information than version 20 and before.
First, the more re ent result of generating an error; then the earlier, version
20 result.
In GNU Ema s version 21, a `*Ba ktra e*' window will open up and you
will see the following in it:
---------- Buffer: *Ba ktra e* ----------
Debugger entered--Lisp error: (void-fun tion this)
(this is an unquoted list)
eval((this is an unquoted list))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
all-intera tively(eval-last-sexp)
---------- Buffer: *Ba ktra e* ----------
Your ursor will be in this window (you may have to wait a few se onds
before it be omes visible). To quit the debugger and make the debugger
window go away, type:
q
Please type q right now, so you be ome on dent that you an get out of
the debugger. Then, type C-x C-e again to re-enter it.
Based on what we already know, we an almost read this error message.
You read the `*Ba ktra e*' bu er from the bottom up; it tells you what
Ema s did. When you typed C-x C-e, you made an intera tive all to the
ommand eval-last-sexp. eval is an abbreviation for `evaluate' and sexp
is an abbreviation for `symboli expression'. The ommand means `evaluate
last symboli expression', whi h is the expression just before your ursor.
Ea h line above tells you what the Lisp interpreter evaluated next. The
most re ent a tion is at the top. The bu er is alled the `*Ba ktra e*'
bu er be ause it enables you to tra k Ema s ba kwards.
6 Chapter 1: List Pro essing

At the top of the `*Ba ktra e*' bu er, you see the line:
Debugger entered--Lisp error: (void-fun tion this)
The Lisp interpreter tried to evaluate the rst atom of the list, the word
`this'. It is this a tion that generated the error message `void-fun tion
this'.
The message ontains the words `void-fun tion' and `this'.
The word `fun tion' was mentioned on e before. It is a very important
word. For our purposes, we an de ne it by saying that a fun tion is a set
of instru tions to the omputer that tell the omputer to do something.
Now we an begin to understand the error message: `void-fun tion
this'. The fun tion (that is, the word `this') does not have a de nition of
any set of instru tions for the omputer to arry out.
The slightly odd word, `void-fun tion', is designed to over the way
Ema s Lisp is implemented, whi h is that when a symbol does not have a
fun tion de nition atta hed to it, the pla e that should ontain the instru -
tions is `void'.
On the other hand, sin e we were able to add 2 plus 2 su essfully, by
evaluating (+ 2 2), we an infer that the symbol + must have a set of in-
stru tions for the omputer to obey and those instru tions must be to add
the numbers that follow the +.
In GNU Ema s version 20, and in earlier versions, you will see only one
line of error message; it will appear in the e ho area and look like this:
Symbol's fun tion definition is void: this
(Also, your terminal may beep at you|some do, some don't; and others
blink. This is just a devi e to get your attention.) The message goes away
as soon as you type another key, even just to move the ursor.
We know the meaning of the word `Symbol'. It refers to the rst atom of
the list, the word `this'. The word `fun tion' refers to the instru tions that
tell the omputer what to do. (Te hni ally, the symbol tells the omputer
where to nd the instru tions, but this is a ompli ation we an ignore for
the moment.)
The error message an be understood: `Symbol's fun tion definition
is void: this'. The symbol (that is, the word `this') la ks instru tions for
the omputer to arry out.

1.4 Symbol Names and Fun tion De nitions


We an arti ulate another hara teristi of Lisp based on what we have
dis ussed so far|an important hara teristi : a symbol, like +, is not itself
the set of instru tions for the omputer to arry out. Instead, the symbol
is used, perhaps temporarily, as a way of lo ating the de nition or set of
instru tions. What we see is the name through whi h the instru tions an
be found. Names of people work the same way. I an be referred to as
The Lisp Interpreter 7

`Bob'; however, I am not the letters `B', `o', `b' but am the ons iousness
onsistently asso iated with a parti ular life-form. The name is not me, but
it an be used to refer to me.
In Lisp, one set of instru tions an be atta hed to several names. For
example, the omputer instru tions for adding numbers an be linked to the
symbol plus as well as to the symbol + (and are in some diale ts of Lisp).
Among humans, I an be referred to as `Robert' as well as `Bob' and by
other words as well.
On the other hand, a symbol an have only one fun tion de nition at-
ta hed to it at a time. Otherwise, the omputer would be onfused as to
whi h de nition to use. If this were the ase among people, only one person
in the world ould be named `Bob'. However, the fun tion de nition to whi h
the name refers an be hanged readily. (See Se tion 3.2, \Install a Fun tion
De nition", page 31.)
Sin e Ema s Lisp is large, it is ustomary to name symbols in a way that
identi es the part of Ema s to whi h the fun tion belongs. Thus, all the
names for fun tions that deal with Texinfo start with `texinfo-' and those
for fun tions that deal with reading mail start with `rmail-'.

1.5 The Lisp Interpreter


Based on what we have seen, we an now start to gure out what the Lisp
interpreter does when we ommand it to evaluate a list. First, it looks to see
whether there is a quote before the list; if there is, the interpreter just gives
us the list. On the other hand, if there is no quote, the interpreter looks at
the rst element in the list and sees whether it has a fun tion de nition. If
it does, the interpreter arries out the instru tions in the fun tion de nition.
Otherwise, the interpreter prints an error message.
This is how Lisp works. Simple. There are added ompli ations whi h
we will get to in a minute, but these are the fundamentals. Of ourse, to
write Lisp programs, you need to know how to write fun tion de nitions and
atta h them to names, and how to do this without onfusing either yourself
or the omputer.
Now, for the rst ompli ation. In addition to lists, the Lisp interpreter
an evaluate a symbol that is not quoted and does not have parentheses
around it. The Lisp interpreter will attempt to determine the symbol's
value as a variable. This situation is des ribed in the se tion on variables.
(See Se tion 1.7, \Variables", page 10.)
The se ond ompli ation o urs be ause some fun tions are unusual and
do not work in the usual manner. Those that don't are alled spe ial forms.
They are used for spe ial jobs, like de ning a fun tion, and there are not
many of them. In the next few hapters, you will be introdu ed to several
of the more important spe ial forms.
8 Chapter 1: List Pro essing

The third and nal ompli ation is this: if the fun tion that the Lisp
interpreter is looking at is not a spe ial form, and if it is part of a list, the
Lisp interpreter looks to see whether the list has a list inside of it. If there
is an inner list, the Lisp interpreter rst gures out what it should do with
the inside list, and then it works on the outside list. If there is yet another
list embedded inside the inner list, it works on that one rst, and so on.
It always works on the innermost list rst. The interpreter works on the
innermost list rst, to evaluate the result of that list. The result may be
used by the en losing expression.
Otherwise, the interpreter works left to right, from one expression to the
next.

1.5.1 Byte Compiling


One other aspe t of interpreting: the Lisp interpreter is able to interpret
two kinds of entity: humanly readable ode, on whi h we will fo us ex lu-
sively, and spe ially pro essed ode, alled byte ompiled ode, whi h is not
humanly readable. Byte ompiled ode runs faster than humanly readable
ode.
You an transform humanly readable ode into byte ompiled ode by
running one of the ompile ommands su h as byte- ompile-file. Byte
ompiled ode is usually stored in a le that ends with a `.el ' exten-
sion rather than a `.el' extension. You will see both kinds of le in the
`ema s/lisp' dire tory; the les to read are those with `.el' extensions.
As a pra ti al matter, for most things you might do to ustomize or
extend Ema s, you do not need to byte ompile; and I will not dis uss
the topi here. See se tion \Byte Compilation" in The GNU Ema s Lisp
Referen e Manual, for a full des ription of byte ompilation.

1.6 Evaluation
When the Lisp interpreter works on an expression, the term for the a -
tivity is alled evaluation. We say that the interpreter `evaluates the expres-
sion'. I've used this term several times before. The word omes from its
use in everyday language, `to as ertain the value or amount of; to appraise',
a ording to Webster's New Collegiate Di tionary.
After evaluating an expression, the Lisp interpreter will most likely return
the value that the omputer produ es by arrying out the instru tions it
found in the fun tion de nition, or perhaps it will give up on that fun tion
and produ e an error message. (The interpreter may also nd itself tossed,
so to speak, to a di erent fun tion or it may attempt to repeat ontinually
what it is doing for ever and ever in what is alled an `in nite loop'. These
a tions are less ommon; and we an ignore them.) Most frequently, the
interpreter returns a value.
Evaluating Inner Lists 9

At the same time the interpreter returns a value, it may do something


else as well, su h as move a ursor or opy a le; this other kind of a tion
is alled a side e e t. A tions that we humans think are important, su h as
printing results, are often \side e e ts" to the Lisp interpreter. The jargon
an sound pe uliar, but it turns out that it is fairly easy to learn to use side
e e ts.
In summary, evaluating a symboli expression most ommonly auses the
Lisp interpreter to return a value and perhaps arry out a side e e t; or else
produ e an error.

1.6.1 Evaluating Inner Lists


If evaluation applies to a list that is inside another list, the outer list may
use the value returned by the rst evaluation as information when the outer
list is evaluated. This explains why inner expressions are evaluated rst: the
values they return are used by the outer expressions.
We an investigate this pro ess by evaluating another addition example.
Pla e your ursor after the following expression and type C-x C-e:
(+ 2 (+ 3 3))
The number 8 will appear in the e ho area.
What happens is that the Lisp interpreter rst evaluates the inner ex-
pression, (+ 3 3), for whi h the value 6 is returned; then it evaluates the
outer expression as if it were written (+ 2 6), whi h returns the value 8.
Sin e there are no more en losing expressions to evaluate, the interpreter
prints that value in the e ho area.
Now it is easy to understand the name of the ommand invoked by the
keystrokes C-x C-e: the name is eval-last-sexp. The letters sexp are
an abbreviation for `symboli expression', and eval is an abbreviation for
`evaluate'. The ommand means `evaluate last symboli expression'.
As an experiment, you an try evaluating the expression by putting the
ursor at the beginning of the next line immediately following the expression,
or inside the expression.
Here is another opy of the expression:
(+ 2 (+ 3 3))
If you pla e the ursor at the beginning of the blank line that immediately
follows the expression and type C-x C-e, you will still get the value 8 printed
in the e ho area. Now try putting the ursor inside the expression. If you
put it right after the next to last parenthesis (so it appears to sit on top
of the last parenthesis), you will get a 6 printed in the e ho area! This is
be ause the ommand evaluates the expression (+ 3 3).
Now put the ursor immediately after a number. Type C-x C-e and you
will get the number itself. In Lisp, if you evaluate a number, you get the
number itself|this is how numbers di er from symbols. If you evaluate a
list starting with a symbol like +, you will get a value returned that is the
10 Chapter 1: List Pro essing

result of the omputer arrying out the instru tions in the fun tion de nition
atta hed to that name. If a symbol by itself is evaluated, something di erent
happens, as we will see in the next se tion.

1.7 Variables
In Ema s Lisp, a symbol an have a value atta hed to it just as it an
have a fun tion de nition atta hed to it. The two are di erent. The fun tion
de nition is a set of instru tions that a omputer will obey. A value, on the
other hand, is something, su h as number or a name, that an vary (whi h
is why su h a symbol is alled a variable). The value of a symbol an be any
expression in Lisp, su h as a symbol, number, list, or string. A symbol that
has a value is often alled a variable.
A symbol an have both a fun tion de nition and a value atta hed to it
at the same time. Or it an have just one or the other. The two are separate.
This is somewhat similar to the way the name Cambridge an refer to the
ity in Massa husetts and have some information atta hed to the name as
well, su h as \great programming enter".
Another way to think about this is to imagine a symbol as being a hest of
drawers. The fun tion de nition is put in one drawer, the value in another,
and so on. What is put in the drawer holding the value an be hanged
without a e ting the ontents of the drawer holding the fun tion de nition,
and vi e-versa.
The variable fill- olumn illustrates a symbol with a value atta hed to
it: in every GNU Ema s bu er, this symbol is set to some value, usually 72
or 70, but sometimes to some other value. To nd the value of this symbol,
evaluate it by itself. If you are reading this in Info inside of GNU Ema s,
you an do this by putting the ursor after the symbol and typing C-x C-e:
fill- olumn
After I typed C-x C-e, Ema s printed the number 72 in my e ho area. This
is the value for whi h fill- olumn is set for me as I write this. It may
be di erent for you in your Info bu er. Noti e that the value returned as
a variable is printed in exa tly the same way as the value returned by a
fun tion arrying out its instru tions. From the point of view of the Lisp
interpreter, a value returned is a value returned. What kind of expression it
ame from eases to matter on e the value is known.
A symbol an have any value atta hed to it or, to use the jargon, we an
bind the variable to a value: to a number, su h as 72; to a string, "su h as
this"; to a list, su h as (spru e pine oak); we an even bind a variable to
a fun tion de nition.
A symbol an be bound to a value in several ways. See Se tion 1.9,
\Setting the Value of a Variable", page 17, for information about one way
to do this.
Error Message for a Symbol Without a Value 11

1.7.1 Error Message for a Symbol Without a Fun tion


When we evaluated fill- olumn to nd its value as a variable, we did
not pla e parentheses around the word. This is be ause we did not intend
to use it as a fun tion name.
If fill- olumn were the rst or only element of a list, the Lisp interpreter
would attempt to nd the fun tion de nition atta hed to it. But fill-
olumn has no fun tion de nition. Try evaluating this:
(fill- olumn)
In GNU Ema s version 21, you will reate a `*Ba ktra e*' bu er that says:
---------- Buffer: *Ba ktra e* ----------
Debugger entered--Lisp error: (void-fun tion fill- olumn)
(fill- olumn)
eval((fill- olumn))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
all-intera tively(eval-last-sexp)
---------- Buffer: *Ba ktra e* ----------
(Remember, to quit the debugger and make the debugger window go away,
type q in the `*Ba ktra e*' bu er.)
In GNU Ema s 20 and before, you will produ e an error message that
says:
Symbol's fun tion definition is void: fill- olumn
(The message will go away away as soon as you move the ursor or type
another key.)

1.7.2 Error Message for a Symbol Without a Value


If you attempt to evaluate a symbol that does not have a value bound
to it, you will re eive an error message. You an see this by experimenting
with our 2 plus 2 addition. In the following expression, put your ursor right
after the +, before the rst number 2, type C-x C-e:
(+ 2 2)
In GNU Ema s 21, you will reate a `*Ba ktra e*' bu er that says:
---------- Buffer: *Ba ktra e* ----------
Debugger entered--Lisp error: (void-variable +)
eval(+)
eval-last-sexp-1(nil)
eval-last-sexp(nil)
all-intera tively(eval-last-sexp)
---------- Buffer: *Ba ktra e* ----------
(As with the other times we entered the debugger, you an quit by typing q
in the `*Ba ktra e*' bu er.)
12 Chapter 1: List Pro essing

This ba ktra e is di erent from the very rst error message we saw,
whi h said, `Debugger entered--Lisp error: (void-fun tion this)'. In
this ase, the fun tion does not have a value as a variable; while in the other
error message, the fun tion (the word `this') did not have a de nition.
In this experiment with the +, what we did was ause the Lisp interpreter
to evaluate the + and look for the value of the variable instead of the fun tion
de nition. We did this by pla ing the ursor right after the symbol rather
than after the parenthesis of the en losing list as we did before. As a onse-
quen e, the Lisp interpreter evaluated the pre eding s-expression, whi h in
this ase was the + by itself.
Sin e + does not have a value bound to it, just the fun tion de nition,
the error message reported that the symbol's value as a variable was void.
In GNU Ema s version 20 and before, your error message will say:
Symbol's value as variable is void: +
The meaning is the same as in GNU Ema s 21.

1.8 Arguments
To see how information is passed to fun tions, let's look again at our old
standby, the addition of two plus two. In Lisp, this is written as follows:
(+ 2 2)
If you evaluate this expression, the number 4 will appear in your e ho
area. What the Lisp interpreter does is add the numbers that follow the +.
The numbers added by + are alled the arguments of the fun tion +.
These numbers are the information that is given to or passed to the fun tion.
The word `argument' omes from the way it is used in mathemati s and
does not refer to a disputation between two people; instead it refers to the
information presented to the fun tion, in this ase, to the +. In Lisp, the
arguments to a fun tion are the atoms or lists that follow the fun tion. The
values returned by the evaluation of these atoms or lists are passed to the
fun tion. Di erent fun tions require di erent numbers of arguments; some
fun tions require none at all.1
1 It is urious to tra k the path by whi h the word `argument' ame to have two di er-
ent meanings, one in mathemati s and the other in everyday English. A ording to
the Oxford English Di tionary, the word derives from the Latin for `to make lear,
prove'; thus it ame to mean, by one thread of derivation, `the eviden e o ered as
proof', whi h is to say, `the information o ered', whi h led to its meaning in Lisp.
But in the other thread of derivation, it ame to mean `to assert in a manner against
whi h others may make ounter assertions', whi h led to the meaning of the word as a
disputation. (Note here that the English word has two di erent de nitions atta hed to
it at the same time. By ontrast, in Ema s Lisp, a symbol annot have two di erent
fun tion de nitions at the same time.)
An Argument as the Value of a Variable or List 13

1.8.1 Arguments' Data Types


The type of data that should be passed to a fun tion depends on what
kind of information it uses. The arguments to a fun tion su h as + must
have values that are numbers, sin e + adds numbers. Other fun tions use
di erent kinds of data for their arguments.
For example, the on at fun tion links together or unites two or more
strings of text to produ e a string. The arguments are strings. Con ate-
nating the two hara ter strings ab , def produ es the single string ab def.
This an be seen by evaluating the following:
( on at "ab " "def")
The value produ ed by evaluating this expression is "ab def".
A fun tion su h as substring uses both a string and numbers as argu-
ments. The fun tion returns a part of the string, a substring of the rst
argument. This fun tion takes three arguments. Its rst argument is the
string of hara ters, the se ond and third arguments are numbers that in-
di ate the beginning and end of the substring. The numbers are a ount
of the number of hara ters (in luding spa es and pun tuations) from the
beginning of the string.
For example, if you evaluate the following:
(substring "The qui k brown fox jumped." 16 19)
you will see "fox" appear in the e ho area. The arguments are the string
and the two numbers.
Note that the string passed to substring is a single atom even though
it is made up of several words separated by spa es. Lisp ounts everything
between the two quotation marks as part of the string, in luding the spa es.
You an think of the substring fun tion as a kind of `atom smasher' sin e it
takes an otherwise indivisible atom and extra ts a part. However, substring
is only able to extra t a substring from an argument that is a string, not
from another type of atom su h as a number or symbol.

1.8.2 An Argument as the Value of a Variable or List


An argument an be a symbol that returns a value when it is evaluated.
For example, when the symbol fill- olumn by itself is evaluated, it returns
a number. This number an be used in an addition.
Position the ursor after the following expression and type C-x C-e:
(+ 2 fill- olumn)
The value will be a number two more than what you get by evaluating
fill- olumn alone. For me, this is 74, be ause the value of fill- olumn is
72.
As we have just seen, an argument an be a symbol that returns a value
when evaluated. In addition, an argument an be a list that returns a value
when it is evaluated. For example, in the following expression, the arguments
14 Chapter 1: List Pro essing

to the fun tion on at are the strings "The " and " red foxes." and the
list (number-to-string (+ 2 fill- olumn)).
( on at "The " (number-to-string (+ 2 fill- olumn)) " red foxes.")
If you evaluate this expression|and if, as with my Ema s, fill- olumn
evaluates to 72|"The 74 red foxes." will appear in the e ho area. (Note
that you must put spa es after the word `The' and before the word `red'
so they will appear in the nal string. The fun tion number-to-string
onverts the integer that the addition fun tion returns to a string. number-
to-string is also known as int-to-string.)

1.8.3 Variable Number of Arguments


Some fun tions, su h as on at, + or *, take any number of arguments.
(The * is the symbol for multipli ation.) This an be seen by evaluating
ea h of the following expressions in the usual way. What you will see in the
e ho area is printed in this text after `)', whi h you may read as `evaluates
to'.
In the rst set, the fun tions have no arguments:
(+) ) 0

(*) ) 1
In this set, the fun tions have one argument ea h:
(+ 3) ) 3

(* 3) ) 3
In this set, the fun tions have three arguments ea h:
(+ 3 4 5) ) 12

(* 3 4 5) ) 60

1.8.4 Using the Wrong Type Obje t as an Argument


When a fun tion is passed an argument of the wrong type, the Lisp
interpreter produ es an error message. For example, the + fun tion expe ts
the values of its arguments to be numbers. As an experiment we an pass it
the quoted symbol hello instead of a number. Position the ursor after the
following expression and type C-x C-e:
(+ 2 'hello)
When you do this you will generate an error message. What has happened is
that + has tried to add the 2 to the value returned by 'hello, but the value
returned by 'hello is the symbol hello, not a number. Only numbers an
be added. So + ould not arry out its addition.
Using the Wrong Type Obje t as an Argument 15

In GNU Ema s version 21, you will reate and enter a `*Ba ktra e*'
bu er that says:
---------- Buffer: *Ba ktra e* ----------
Debugger entered--Lisp error:
(wrong-type-argument number-or-marker-p hello)
+(2 hello)
eval((+ 2 (quote hello)))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
all-intera tively(eval-last-sexp)
---------- Buffer: *Ba ktra e* ----------

As usual, the error message tries to be helpful and makes sense after you
learn how to read it.
The rst part of the error message is straightforward; it says `wrong type
argument'. Next omes the mysterious jargon word `number-or-marker-p'.
This word is trying to tell you what kind of argument the + expe ted.
The symbol number-or-marker-p says that the Lisp interpreter is try-
ing to determine whether the information presented it (the value of the
argument) is a number or a marker (a spe ial obje t representing a bu er
position). What it does is test to see whether the + is being given numbers to
add. It also tests to see whether the argument is something alled a marker,
whi h is a spe i feature of Ema s Lisp. (In Ema s, lo ations in a bu er
are re orded as markers. When the mark is set with the C- or C-hSPCi
ommand, its position is kept as a marker. The mark an be onsidered a
number|the number of hara ters the lo ation is from the beginning of the
bu er.) In Ema s Lisp, + an be used to add the numeri value of marker
positions as numbers.
The `p' of number-or-marker-p is the embodiment of a pra ti e started
in the early days of Lisp programming. The `p' stands for `predi ate'. In the
jargon used by the early Lisp resear hers, a predi ate refers to a fun tion
to determine whether some property is true or false. So the `p' tells us that
number-or-marker-p is the name of a fun tion that determines whether it
is true or false that the argument supplied is a number or a marker. Other
Lisp symbols that end in `p' in lude zerop, a fun tion that tests whether its
argument has the value of zero, and listp, a fun tion that tests whether its
argument is a list.
Finally, the last part of the error message is the symbol hello. This is the
value of the argument that was passed to +. If the addition had been passed
the orre t type of obje t, the value passed would have been a number, su h
as 37, rather than a symbol like hello. But then you would not have got
the error message.
16 Chapter 1: List Pro essing

In GNU Ema s version 20 and before, the e ho area displays an error


message that says:
Wrong type argument: number-or-marker-p, hello
This says, in di erent words, the same as the top line of the `*Ba ktra e*'
bu er.
1.8.5 The message Fun tion
Like +, the message fun tion takes a variable number of arguments. It is
used to send messages to the user and is so useful that we will des ribe it
here.
A message is printed in the e ho area. For example, you an print a
message in your e ho area by evaluating the following list:
(message "This message appears in the e ho area!")
The whole string between double quotation marks is a single argument
and is printed in toto. (Note that in this example, the message itself will ap-
pear in the e ho area within double quotes; that is be ause you see the value
returned by the message fun tion. In most uses of message in programs that
you write, the text will be printed in the e ho area as a side-e e t, without
the quotes. See Se tion 3.3.1, \multiply-by-seven in detail", page 34, for
an example of this.)
However, if there is a `%s' in the quoted string of hara ters, the message
fun tion does not print the `%s' as su h, but looks to the argument that
follows the string. It evaluates the se ond argument and prints the value at
the lo ation in the string where the `%s' is.
You an see this by positioning the ursor after the following expression
and typing C-x C-e:
(message "The name of this buffer is: %s." (buffer-name))
In Info, "The name of this buffer is: *info*." will appear in the e ho
area. The fun tion buffer-name returns the name of the bu er as a string,
whi h the message fun tion inserts in pla e of %s.
To print a value as an integer, use `%d' in the same way as `%s'. For
example, to print a message in the e ho area that states the value of the
fill- olumn, evaluate the following:
(message "The value of fill- olumn is %d." fill- olumn)
On my system, when I evaluate this list, "The value of fill- olumn is
72." appears in my e ho area2 .
If there is more than one `%s' in the quoted string, the value of the rst
argument following the quoted string is printed at the lo ation of the rst
`%s' and the value of the se ond argument is printed at the lo ation of the
se ond `%s', and so on.
2 A tually, you an use %s to print a number. It is non-spe i . %d prints only the part
of a number left of a de imal point, and not anything that is not a number.
Using set 17

For example, if you evaluate the following,


(message "There are %d %s in the offi e!"
(- fill- olumn 14) "pink elephants")
a rather whimsi al message will appear in your e ho area. On my system it
says, "There are 58 pink elephants in the offi e!".
The expression (- fill- olumn 14) is evaluated and the resulting num-
ber is inserted in pla e of the `%d'; and the string in double quotes, "pink
elephants", is treated as a single argument and inserted in pla e of the
`%s'. (That is to say, a string between double quotes evaluates to itself, like
a number.)
Finally, here is a somewhat omplex example that not only illustrates
the omputation of a number, but also shows how you an use an expression
within an expression to generate the text that is substituted for `%s':
(message "He saw %d %s"
(- fill- olumn 34)
( on at "red "
(substring
"The qui k brown foxes jumped." 16 21)
" leaping."))
In this example, message has three arguments: the string, "He saw %d
%s", the expression, (- fill- olumn 32), and the expression beginning with
the fun tion on at. The value resulting from the evaluation of (- fill-
olumn 32) is inserted in pla e of the `%d'; and the value returned by the
expression beginning with on at is inserted in pla e of the `%s'.
When I evaluate the expression, the message "He saw 38 red foxes
leaping." appears in my e ho area.

1.9 Setting the Value of a Variable


There are several ways by whi h a variable an be given a value. One of
the ways is to use either the fun tion set or the fun tion setq. Another way
is to use let (see Se tion 3.6, \let", page 36). (The jargon for this pro ess
is to bind a variable to a value.)
The following se tions not only des ribe how set and setq work but also
illustrate how arguments are passed.

1.9.1 Using set


To set the value of the symbol flowers to the list '(rose violet daisy
butter up), evaluate the following expression by positioning the ursor after
the expression and typing C-x C-e.
(set 'flowers '(rose violet daisy butter up))
18 Chapter 1: List Pro essing

The list (rose violet daisy butter up) will appear in the e ho area. This
is what is returned by the set fun tion. As a side e e t, the symbol flowers
is bound to the list ; that is, the symbol flowers, whi h an be viewed as a
variable, is given the list as its value. (This pro ess, by the way, illustrates
how a side e e t to the Lisp interpreter, setting the value, an be the primary
e e t that we humans are interested in. This is be ause every Lisp fun tion
must return a value if it does not get an error, but it will only have a side
e e t if it is designed to have one.)
After evaluating the set expression, you an evaluate the symbol flowers
and it will return the value you just set. Here is the symbol. Pla e your
ursor after it and type C-x C-e.
flowers
When you evaluate flowers, the list (rose violet daisy butter up) ap-
pears in the e ho area.
In identally, if you evaluate 'flowers, the variable with a quote in front
of it, what you will see in the e ho area is the symbol itself, flowers. Here
is the quoted symbol, so you an try this:
'flowers
Note also, that when you use set, you need to quote both arguments to
set, unless you want them evaluated. Sin e we do not want either argument
evaluated, neither the variable flowers nor the list (rose violet daisy
butter up), both are quoted. (When you use set without quoting its rst
argument, the rst argument is evaluated before anything else is done. If
you did this and flowers did not have a value already, you would get an
error message that the `Symbol's value as variable is void'; on the other
hand, if flowers did return a value after it was evaluated, the set would
attempt to set the value that was returned. There are situations where this
is the right thing for the fun tion to do; but su h situations are rare.)

1.9.2 Using setq


As a pra ti al matter, you almost always quote the rst argument to set.
The ombination of set and a quoted rst argument is so ommon that it
has its own name: the spe ial form setq. This spe ial form is just like set
ex ept that the rst argument is quoted automati ally, so you don't need to
type the quote mark yourself. Also, as an added onvenien e, setq permits
you to set several di erent variables to di erent values, all in one expression.
To set the value of the variable arnivores to the list '(lion tiger
leopard) using setq, the following expression is used:
(setq arnivores '(lion tiger leopard))
This is exa tly the same as using set ex ept the rst argument is automat-
i ally quoted by setq. (The `q' in setq means quote.)
Counting 19

With set, the expression would look like this:


(set ' arnivores '(lion tiger leopard))
Also, setq an be used to assign di erent values to di erent variables.
The rst argument is bound to the value of the se ond argument, the third
argument is bound to the value of the fourth argument, and so on. For
example, you ould use the following to assign a list of trees to the symbol
trees and a list of herbivores to the symbol herbivores:
(setq trees '(pine fir oak maple)
herbivores '(gazelle antelope zebra))
(The expression ould just as well have been on one line, but it might not
have t on a page; and humans nd it easier to read ni ely formatted lists.)
Although I have been using the term `assign', there is another way of
thinking about the workings of set and setq; and that is to say that set
and setq make the symbol point to the list. This latter way of thinking is
very ommon and in forth oming hapters we shall ome upon at least one
symbol that has `pointer' as part of its name. The name is hosen be ause the
symbol has a value, spe i ally a list, atta hed to it; or, expressed another
way, the symbol is set to \point" to the list.

1.9.3 Counting
Here is an example that shows how to use setq in a ounter. You might
use this to ount how many times a part of your program repeats itself. First
set a variable to zero; then add one to the number ea h time the program
repeats itself. To do this, you need a variable that serves as a ounter, and
two expressions: an initial setq expression that sets the ounter variable to
zero; and a se ond setq expression that in rements the ounter ea h time it
is evaluated.
(setq ounter 0) ; Let's all this the initializer.

(setq ounter (+ ounter 1)) ; This is the in rementer.

ounter ; This is the ounter.


(The text following the `;' are omments. See Se tion 3.2.1, \Change a
Fun tion De nition", page 32.)
If you evaluate the rst of these expressions, the initializer, (setq
ounter 0), and then evaluate the third expression, ounter, the number 0
will appear in the e ho area. If you then evaluate the se ond expression, the
in rementer, (setq ounter (+ ounter 1)), the ounter will get the value
1. So if you again evaluate ounter, the number 1 will appear in the e ho
area. Ea h time you evaluate the se ond expression, the value of the ounter
will be in remented.
When you evaluate the in rementer, (setq ounter (+ ounter 1)), the
Lisp interpreter rst evaluates the innermost list; this is the addition. In
20 Chapter 1: List Pro essing

order to evaluate this list, it must evaluate the variable ounter and the
number 1. When it evaluates the variable ounter, it re eives its urrent
value. It passes this value and the number 1 to the + whi h adds them
together. The sum is then returned as the value of the inner list and passed
to the setq whi h sets the variable ounter to this new value. Thus, the
value of the variable, ounter, is hanged.

1.10 Summary
Learning Lisp is like limbing a hill in whi h the rst part is the steepest.
You have now limbed the most diÆ ult part; what remains be omes easier
as you progress onwards.
In summary,
 Lisp programs are made up of expressions, whi h are lists or single
atoms.
 Lists are made up of zero or more atoms or inner lists, separated by
whitespa e and surrounded by parentheses. A list an be empty.
 Atoms are multi- hara ter symbols, like forward-paragraph, single
hara ter symbols like +, strings of hara ters between double quota-
tion marks, or numbers.
 A number evaluates to itself.
 A string between double quotes also evaluates to itself.
 When you evaluate a symbol by itself, its value is returned.
 When you evaluate a list, the Lisp interpreter looks at the rst symbol
in the list and then at the fun tion de nition bound to that symbol.
Then the instru tions in the fun tion de nition are arried out.
 A single-quote, ', tells the Lisp interpreter that it should return the
following expression as written, and not evaluate it as it would if the
quote were not there.
 Arguments are the information passed to a fun tion. The arguments to
a fun tion are omputed by evaluating the rest of the elements of the
list of whi h the fun tion is the rst element.
 A fun tion always returns a value when it is evaluated (unless it gets
an error); in addition, it may also arry out some a tion alled a \side
e e t". In many ases, a fun tion's primary purpose is to reate a side
e e t.

1.11 Exer ises


A few simple exer ises:
 Generate an error message by evaluating an appropriate symbol that is
not within parentheses.
Exer ises 21

 Generate an error message by evaluating an appropriate symbol that is


between parentheses.
 Create a ounter that in rements by two rather than one.
 Write an expression that prints a message in the e ho area when evalu-
ated.
22 Chapter 1: List Pro essing
Bu er Names 23

2 Pra ti ing Evaluation


Before learning how to write a fun tion de nition in Ema s Lisp, it is
useful to spend a little time evaluating various expressions that have already
been written. These expressions will be lists with the fun tions as their rst
(and often only) element. Sin e some of the fun tions asso iated with bu ers
are both simple and interesting, we will start with those. In this se tion, we
will evaluate a few of these. In another se tion, we will study the ode of
several other bu er-related fun tions, to see how they were written.
Whenever you give an editing ommand to Ema s Lisp, su h as the om-
mand to move the ursor or to s roll the s reen, you are evaluating an ex-
pression, the rst element of whi h is a fun tion. This is how Ema s works.
When you type keys, you ause the Lisp interpreter to evaluate an expres-
sion and that is how you get your results. Even typing plain text involves
evaluating an Ema s Lisp fun tion, in this ase, one that uses self-insert-
ommand, whi h simply inserts the hara ter you typed. The fun tions you
evaluate by typing keystrokes are alled intera tive fun tions, or ommands;
how you make a fun tion intera tive will be illustrated in the hapter on
how to write fun tion de nitions. See Se tion 3.3, \Making a Fun tion In-
tera tive", page 33.
In addition to typing keyboard ommands, we have seen a se ond way
to evaluate an expression: by positioning the ursor after a list and typing
C-x C-e. This is what we will do in the rest of this se tion. There are other
ways to evaluate an expression as well; these will be des ribed as we ome
to them.
Besides being used for pra ti ing evaluation, the fun tions shown in the
next few se tions are important in their own right. A study of these fun tions
makes lear the distin tion between bu ers and les, how to swit h to a
bu er, and how to determine a lo ation within it.

2.1 Bu er Names
The two fun tions, buffer-name and buffer-file-name, show the di er-
en e between a le and a bu er. When you evaluate the following expression,
(buffer-name), the name of the bu er appears in the e ho area. When you
evaluate (buffer-file-name), the name of the le to whi h the bu er refers
appears in the e ho area. Usually, the name returned by (buffer-name) is
the same as the name of the le to whi h it refers, and the name returned
by (buffer-file-name) is the full path-name of the le.
A le and a bu er are two di erent entities. A le is information re orded
permanently in the omputer (unless you delete it). A bu er, on the other
hand, is information inside of Ema s that will vanish at the end of the editing
session (or when you kill the bu er). Usually, a bu er ontains information
that you have opied from a le; we say the bu er is visiting that le. This
opy is what you work on and modify. Changes to the bu er do not hange
24 Chapter 2: Pra ti ing Evaluation

the le, until you save the bu er. When you save the bu er, the bu er is
opied to the le and is thus saved permanently.
If you are reading this in Info inside of GNU Ema s, you an evaluate
ea h of the following expressions by positioning the ursor after it and typing
C-x C-e.
(buffer-name)

(buffer-file-name)
When I do this, `"introdu tion.texinfo"' is the value returned by eval-
uating (buffer-name), and `"/gnu/work/intro/introdu tion.texinfo"'
is the value returned by evaluating (buffer-file-name). The former is the
name of the bu er and the latter is the name of the le. (In the expres-
sions, the parentheses tell the Lisp interpreter to treat buffer-name and
buffer-file-name as fun tions; without the parentheses, the interpreter
would attempt to evaluate the symbols as variables. See Se tion 1.7, \Vari-
ables", page 10.)
In spite of the distin tion between les and bu ers, you will often nd
that people refer to a le when they mean a bu er and vi e-versa. Indeed,
most people say, \I am editing a le," rather than saying, \I am editing a
bu er whi h I will soon save to a le." It is almost always lear from ontext
what people mean. When dealing with omputer programs, however, it is
important to keep the distin tion in mind, sin e the omputer is not as smart
as a person.
The word `bu er', by the way, omes from the meaning of the word as
a ushion that deadens the for e of a ollision. In early omputers, a bu er
ushioned the intera tion between les and the omputer's entral pro essing
unit. The drums or tapes that held a le and the entral pro essing unit
were pie es of equipment that were very di erent from ea h other, working
at their own speeds, in spurts. The bu er made it possible for them to work
together e e tively. Eventually, the bu er grew from being an intermediary,
a temporary holding pla e, to being the pla e where work is done. This
transformation is rather like that of a small seaport that grew into a great
ity: on e it was merely the pla e where argo was warehoused temporarily
before being loaded onto ships; then it be ame a business and ultural enter
in its own right.
Not all bu ers are asso iated with les. For example, when you start
an Ema s session by typing the ommand ema s alone, without naming any
les, Ema s will start with the `*s rat h*' bu er on the s reen. This bu er
is not visiting any le. Similarly, a `*Help*' bu er is not asso iated with
any le.
If you swit h to the `*s rat h*' bu er, type (buffer-name), position
the ursor after it, and type C-x C-e to evaluate the expression, the name
"*s rat h*" is returned and will appear in the e ho area. "*s rat h*"
is the name of the bu er. However, if you type (buffer-file-name) in
Getting Bu ers 25

the `*s rat h*' bu er and evaluate that, nil will appear in the e ho area.
nil is from the Latin word for `nothing'; in this ase, it means that the
`*s rat h*' bu er is not asso iated with any le. (In Lisp, nil is also used
to mean `false' and is a synonym for the empty list, ().)
In identally, if you are in the `*s rat h*' bu er and want the value
returned by an expression to appear in the `*s rat h*' bu er itself rather
than in the e ho area, type C-u C-x C-e instead of C-x C-e. This auses the
value returned to appear after the expression. The bu er will look like this:
(buffer-name)"*s rat h*"
You annot do this in Info sin e Info is read-only and it will not allow you
to hange the ontents of the bu er. But you an do this in any bu er you
an edit; and when you write ode or do umentation (su h as this book),
this feature is very useful.

2.2 Getting Bu ers


The buffer-name fun tion returns the name of the bu er; to get the
bu er itself, a di erent fun tion is needed: the urrent-buffer fun tion. If
you use this fun tion in ode, what you get is the bu er itself.
A name and the obje t or entity to whi h the name refers are di erent
from ea h other. You are not your name. You are a person to whom others
refer by name. If you ask to speak to George and someone hands you a
ard with the letters `G', `e', `o', `r', `g', and `e' written on it, you might be
amused, but you would not be satis ed. You do not want to speak to the
name, but to the person to whom the name refers. A bu er is similar: the
name of the s rat h bu er is `*s rat h*', but the name is not the bu er.
To get a bu er itself, you need to use a fun tion su h as urrent-buffer.
However, there is a slight ompli ation: if you evaluate urrent-buffer
in an expression on its own, as we will do here, what you see is a printed
representation of the name of the bu er without the ontents of the bu er.
Ema s works this way for two reasons: the bu er may be thousands of lines
long|too long to be onveniently displayed; and, another bu er may have
the same ontents but a di erent name, and it is important to distinguish
between them.
Here is an expression ontaining the fun tion:
( urrent-buffer)
If you evaluate the expression in the usual way, `#<buffer *info*>' appears
in the e ho area. The spe ial format indi ates that the bu er itself is being
returned, rather than just its name.
In identally, while you an type a number or symbol into a program, you
annot do that with the printed representation of a bu er: the only way to
get a bu er itself is with a fun tion su h as urrent-buffer.
A related fun tion is other-buffer. This returns the most re ently se-
le ted bu er other than the one you are in urrently. If you have re ently
26 Chapter 2: Pra ti ing Evaluation

swit hed ba k and forth from the `*s rat h*' bu er, other-buffer will
return that bu er.
You an see this by evaluating the expression:
(other-buffer)
You should see `#<buffer *s rat h*>' appear in the e ho area, or the name
of whatever other bu er you swit hed ba k from most re ently1 .

2.3 Swit hing Bu ers


The other-buffer fun tion a tually provides a bu er when it is used
as an argument to a fun tion that requires one. We an see this by using
other-buffer and swit h-to-buffer to swit h to a di erent bu er.
But rst, a brief introdu tion to the swit h-to-buffer fun tion. When
you swit hed ba k and forth from Info to the `*s rat h*' bu er to evaluate
(buffer-name), you most likely typed C-x b and then typed `*s rat h*'2
when prompted in the minibu er for the name of the bu er to whi h you
wanted to swit h. The keystrokes, C-x b, ause the Lisp interpreter to eval-
uate the intera tive fun tion swit h-to-buffer. As we said before, this is
how Ema s works: di erent keystrokes all or run di erent fun tions. For
example, C-f alls forward- har, M-e alls forward-senten e, and so on.
By writing swit h-to-buffer in an expression, and giving it a bu er to
swit h to, we an swit h bu ers just the way C-x b does.
Here is the Lisp expression:
(swit h-to-buffer (other-buffer))
The symbol swit h-to-buffer is the rst element of the list, so the Lisp
interpreter will treat it as a fun tion and arry out the instru tions that
are atta hed to it. But before doing that, the interpreter will note that
other-buffer is inside parentheses and work on that symbol rst. other-
buffer is the rst (and in this ase, the only) element of this list, so the Lisp
interpreter alls or runs the fun tion. It returns another bu er. Next, the
interpreter runs swit h-to-buffer, passing to it, as an argument, the other
bu er, whi h is what Ema s will swit h to. If you are reading this in Info,
try this now. Evaluate the expression. (To get ba k, type C-x b hRETi.)3
1 A tually, by default, if the bu er from whi h you just swit hed is visible to you in
another window, other-buffer will hoose the most re ent bu er that you annot see;
this is a subtlety that I often forget.
2 Or rather, to save typing, you probably typed just part of the name, su h as *s , and
then pressed your TAB key to ause it to expand to the full name; and then typed your
RET key.
3 Remember, this expression will move you to your most re ent other bu er that you
annot see. If you really want to go to your most re ently sele ted bu er, even if you
an still see it, you need to evaluate the following more omplex expression:
(swit h-to-buffer (other-buffer ( urrent-buffer) t))
Bu er Size and the Lo ation of Point 27

In the programming examples in later se tions of this do ument, you will


see the fun tion set-buffer more often than swit h-to-buffer. This is
be ause of a di eren e between omputer programs and humans: humans
have eyes and expe t to see the bu er on whi h they are working on their
omputer terminals. This is so obvious, it almost goes without saying. How-
ever, programs do not have eyes. When a omputer program works on a
bu er, that bu er does not need to be visible on the s reen.
swit h-to-buffer is designed for humans and does two di erent things:
it swit hes the bu er to whi h Ema s' attention is dire ted; and it swit hes
the bu er displayed in the window to the new bu er. set-buffer, on the
other hand, does only one thing: it swit hes the attention of the omputer
program to a di erent bu er. The bu er on the s reen remains un hanged (of
ourse, normally nothing happens there until the ommand nishes running).
Also, we have just introdu ed another jargon term, the word all. When
you evaluate a list in whi h the rst symbol is a fun tion, you are alling
that fun tion. The use of the term omes from the notion of the fun tion as
an entity that an do something for you if you ` all' it|just as a plumber is
an entity who an x a leak if you all him or her.

2.4 Bu er Size and the Lo ation of Point


Finally, let's look at several rather simple fun tions, buffer-size, point,
point-min, and point-max. These give information about the size of a bu er
and the lo ation of point within it.
The fun tion buffer-size tells you the size of the urrent bu er; that
is, the fun tion returns a ount of the number of hara ters in the bu er.
(buffer-size)
You an evaluate this in the usual way, by positioning the ursor after the
expression and typing C-x C-e.
In Ema s, the urrent position of the ursor is alled point. The expres-
sion (point) returns a number that tells you where the ursor is lo ated as
a ount of the number of hara ters from the beginning of the bu er up to
point.
You an see the hara ter ount for point in this bu er by evaluating the
following expression in the usual way:
(point)
As I write this, the value of point is 65724. The point fun tion is frequently
used in some of the examples later in this book.

In this ase, the rst argument to other-buffer tells it whi h bu er to skip|the


urrent one|and the se ond argument tells other-buffer it is OK to swit h to a
visible bu er. In regular use, swit h-to-buffer takes you to an invisible window
sin e you would most likely use C-x o (other-window) to go to another visible bu er.
28 Chapter 2: Pra ti ing Evaluation

The value of point depends, of ourse, on its lo ation within the bu er.
If you evaluate point in this spot, the number will be larger:
(point)
For me, the value of point in this lo ation is 66043, whi h means that there
are 319 hara ters (in luding spa es) between the two expressions.
The fun tion point-min is somewhat similar to point, but it returns the
value of the minimum permissible value of point in the urrent bu er. This
is the number 1 unless narrowing is in e e t. (Narrowing is a me hanism
whereby you an restri t yourself, or a program, to operations on just a part
of a bu er. See Chapter 6, \Narrowing and Widening", page 77.) Likewise,
the fun tion point-max returns the value of the maximum permissible value
of point in the urrent bu er.

2.5 Exer ise


Find a le with whi h you are working and move towards its middle.
Find its bu er name, le name, length, and your position in the le.
The defun Spe ial Form 29

3 How To Write Fun tion De nitions


When the Lisp interpreter evaluates a list, it looks to see whether the rst
symbol on the list has a fun tion de nition atta hed to it; or, put another
way, whether the symbol points to a fun tion de nition. If it does, the
omputer arries out the instru tions in the de nition. A symbol that has a
fun tion de nition is alled, simply, a fun tion (although, properly speaking,
the de nition is the fun tion and the symbol refers to it.)
All fun tions are de ned in terms of other fun tions, ex ept for a few
primitive fun tions that are written in the C programming language. When
you write fun tions' de nitions, you will write them in Ema s Lisp and use
other fun tions as your building blo ks. Some of the fun tions you will use
will themselves be written in Ema s Lisp (perhaps by you) and some will be
primitives written in C. The primitive fun tions are used exa tly like those
written in Ema s Lisp and behave like them. They are written in C so we
an easily run GNU Ema s on any omputer that has suÆ ient power and
an run C.
Let me re-emphasize this: when you write ode in Ema s Lisp, you do
not distinguish between the use of fun tions written in C and the use of
fun tions written in Ema s Lisp. The di eren e is irrelevant. I mention
the distin tion only be ause it is interesting to know. Indeed, unless you
investigate, you won't know whether an already-written fun tion is written
in Ema s Lisp or C.

3.1 The defun Spe ial Form


In Lisp, a symbol su h as mark-whole-buffer has ode atta hed to it that
tells the omputer what to do when the fun tion is alled. This ode is alled
the fun tion de nition and is reated by evaluating a Lisp expression that
starts with the symbol defun (whi h is an abbreviation for de ne fun tion ).
Be ause defun does not evaluate its arguments in the usual way, it is alled
a spe ial form.
In subsequent se tions, we will look at fun tion de nitions from the Ema s
sour e ode, su h as mark-whole-buffer. In this se tion, we will des ribe
a simple fun tion de nition so you an see how it looks. This fun tion
de nition uses arithmeti be ause it makes for a simple example. Some
people dislike examples using arithmeti ; however, if you are su h a person,
do not despair. Hardly any of the ode we will study in the remainder of
this introdu tion involves arithmeti or mathemati s. The examples mostly
involve text in one way or another.
A fun tion de nition has up to ve parts following the word defun:
1. The name of the symbol to whi h the fun tion de nition should be
atta hed.
2. A list of the arguments that will be passed to the fun tion. If no argu-
ments will be passed to the fun tion, this is an empty list, ().
30 Chapter 3: How To Write Fun tion De nitions

3. Do umentation des ribing the fun tion. (Te hni ally optional, but
strongly re ommended.)
4. Optionally, an expression to make the fun tion intera tive so you an
use it by typing M-x and then the name of the fun tion; or by typing an
appropriate key or key hord.
5. The ode that instru ts the omputer what to do: the body of the
fun tion de nition.
It is helpful to think of the ve parts of a fun tion de nition as being
organized in a template, with slots for ea h part:
(defun fun tion-name (arguments ...)
"optional-do umentation..."
(intera tive argument-passing-info ) ; optional
body ...)
As an example, here is the ode for a fun tion that multiplies its argument
by 7. (This example is not intera tive. See Se tion 3.3, \Making a Fun tion
Intera tive", page 33, for that information.)
(defun multiply-by-seven (number)
"Multiply NUMBER by seven."
(* 7 number))
This de nition begins with a parenthesis and the symbol defun, followed
by the name of the fun tion.
The name of the fun tion is followed by a list that ontains the arguments
that will be passed to the fun tion. This list is alled the argument list. In
this example, the list has only one element, the symbol, number. When the
fun tion is used, the symbol will be bound to the value that is used as the
argument to the fun tion.
Instead of hoosing the word number for the name of the argument, I
ould have pi ked any other name. For example, I ould have hosen the
word multipli and. I pi ked the word `number' be ause it tells what kind
of value is intended for this slot; but I ould just as well have hosen the
word `multipli and' to indi ate the role that the value pla ed in this slot
will play in the workings of the fun tion. I ould have alled it foogle, but
that would have been a bad hoi e be ause it would not tell humans what it
means. The hoi e of name is up to the programmer and should be hosen
to make the meaning of the fun tion lear.
Indeed, you an hoose any name you wish for a symbol in an argument
list, even the name of a symbol used in some other fun tion: the name
you use in an argument list is private to that parti ular de nition. In that
de nition, the name refers to a di erent entity than any use of the same name
outside the fun tion de nition. Suppose you have a ni k-name `Shorty' in
your family; when your family members refer to `Shorty', they mean you.
But outside your family, in a movie, for example, the name `Shorty' refers to
someone else. Be ause a name in an argument list is private to the fun tion
Install a Fun tion De nition 31

de nition, you an hange the value of su h a symbol inside the body of a


fun tion without hanging its value outside the fun tion. The e e t is similar
to that produ ed by a let expression. (See Se tion 3.6, \let", page 36.)
The argument list is followed by the do umentation string that des ribes
the fun tion. This is what you see when you type C-h f and the name of a
fun tion. In identally, when you write a do umentation string like this, you
should make the rst line a omplete senten e sin e some ommands, su h as
apropos, print only the rst line of a multi-line do umentation string. Also,
you should not indent the se ond line of a do umentation string, if you have
one, be ause that looks odd when you use C-h f (des ribe-fun tion). The
do umentation string is optional, but it is so useful, it should be in luded in
almost every fun tion you write.
The third line of the example onsists of the body of the fun tion de ni-
tion. (Most fun tions' de nitions, of ourse, are longer than this.) In this
fun tion, the body is the list, (* 7 number), whi h says to multiply the value
of number by 7. (In Ema s Lisp, * is the fun tion for multipli ation, just as
+ is the fun tion for addition.)
When you use the multiply-by-seven fun tion, the argument number
evaluates to the a tual number you want used. Here is an example that
shows how multiply-by-seven is used; but don't try to evaluate this yet!
(multiply-by-seven 3)
The symbol number, spe i ed in the fun tion de nition in the next se tion,
is given or \bound to" the value 3 in the a tual use of the fun tion. Note
that although number was inside parentheses in the fun tion de nition, the
argument passed to the multiply-by-seven fun tion is not in parentheses.
The parentheses are written in the fun tion de nition so the omputer an
gure out where the argument list ends and the rest of the fun tion de nition
begins.
If you evaluate this example, you are likely to get an error message. (Go
ahead, try it!) This is be ause we have written the fun tion de nition, but
not yet told the omputer about the de nition|we have not yet installed (or
`loaded') the fun tion de nition in Ema s. Installing a fun tion is the pro ess
that tells the Lisp interpreter the de nition of the fun tion. Installation is
des ribed in the next se tion.

3.2 Install a Fun tion De nition


If you are reading this inside of Info in Ema s, you an try out the
multiply-by-seven fun tion by rst evaluating the fun tion de nition and
then evaluating (multiply-by-seven 3). A opy of the fun tion de nition
follows. Pla e the ursor after the last parenthesis of the fun tion de nition
and type C-x C-e. When you do this, multiply-by-seven will appear in the
e ho area. (What this means is that when a fun tion de nition is evaluated,
32 Chapter 3: How To Write Fun tion De nitions

the value it returns is the name of the de ned fun tion.) At the same time,
this a tion installs the fun tion de nition.
(defun multiply-by-seven (number)
"Multiply NUMBER by seven."
(* 7 number))
By evaluating this defun, you have just installed multiply-by-seven in
Ema s. The fun tion is now just as mu h a part of Ema s as forward-
word or any other editing fun tion you use. (multiply-by-seven will stay
installed until you quit Ema s. To reload ode automati ally whenever you
start Ema s, see Se tion 3.5, \Installing Code Permanently", page 36.)
You an see the e e t of installing multiply-by-seven by evaluating the
following sample. Pla e the ursor after the following expression and type
C-x C-e. The number 21 will appear in the e ho area.
(multiply-by-seven 3)
If you wish, you an read the do umentation for the fun tion by typing
C-h f (des ribe-fun tion) and then the name of the fun tion, multiply-
by-seven. When you do this, a `*Help*' window will appear on your s reen
that says:
multiply-by-seven:
Multiply NUMBER by seven.
(To return to a single window on your s reen, type C-x 1.)

3.2.1 Change a Fun tion De nition


If you want to hange the ode in multiply-by-seven, just rewrite it.
To install the new version in pla e of the old one, evaluate the fun tion
de nition again. This is how you modify ode in Ema s. It is very simple.
As an example, you an hange the multiply-by-seven fun tion to add
the number to itself seven times instead of multiplying the number by seven.
It produ es the same answer, but by a di erent path. At the same time, we
will add a omment to the ode; a omment is text that the Lisp interpreter
ignores, but that a human reader may nd useful or enlightening. The
omment is that this is the \se ond version".
(defun multiply-by-seven (number) ; Se ond version.
"Multiply NUMBER by seven."
(+ number number number number number number number))
The omment follows a semi olon, `;'. In Lisp, everything on a line that
follows a semi olon is a omment. The end of the line is the end of the
omment. To stret h a omment over two or more lines, begin ea h line
with a semi olon.
See Se tion 16.3, \Beginning a `.ema s' File", page 216, and se tion
\Comments" in The GNU Ema s Lisp Referen e Manual, for more about
omments.
Make a Fun tion Intera tive 33

You an install this version of the multiply-by-seven fun tion by eval-


uating it in the same way you evaluated the rst fun tion: pla e the ursor
after the last parenthesis and type C-x C-e.
In summary, this is how you write ode in Ema s Lisp: you write a
fun tion; install it; test it; and then make xes or enhan ements and install
it again.

3.3 Make a Fun tion Intera tive


You make a fun tion intera tive by pla ing a list that begins with the
spe ial form intera tive immediately after the do umentation. A user
an invoke an intera tive fun tion by typing M-x and then the name of the
fun tion; or by typing the keys to whi h it is bound, for example, by typing
C-n for next-line or C-x h for mark-whole-buffer.
Interestingly, when you all an intera tive fun tion intera tively, the value
returned is not automati ally displayed in the e ho area. This is be ause you
often all an intera tive fun tion for its side e e ts, su h as moving forward
by a word or line, and not for the value returned. If the returned value
were displayed in the e ho area ea h time you typed a key, it would be very
distra ting.
Both the use of the spe ial form intera tive and one way to display a
value in the e ho area an be illustrated by reating an intera tive version
of multiply-by-seven.
Here is the ode:
(defun multiply-by-seven (number) ; Intera tive version.
"Multiply NUMBER by seven."
(intera tive "p")
(message "The result is %d" (* 7 number)))
You an install this ode by pla ing your ursor after it and typing C-x C-e.
The name of the fun tion will appear in your e ho area. Then, you an use
this ode by typing C-u and a number and then typing M-x multiply-by-
seven and pressing hRETi. The phrase `The result is ...' followed by the
produ t will appear in the e ho area.
Speaking more generally, you invoke a fun tion like this in either of two
ways:
1. By typing a pre x argument that ontains the number to be passed,
and then typing M-x and the name of the fun tion, as with C-u 3 M-x
forward-senten e; or,
2. By typing whatever key or key hord the fun tion is bound to, as with
C-u 3 M-e.
Both the examples just mentioned work identi ally to move point forward
three senten es. (Sin e multiply-by-seven is not bound to a key, it ould
not be used as an example of key binding.)
34 Chapter 3: How To Write Fun tion De nitions

(See Se tion 16.7, \Some Keybindings", page 220, to learn how to bind
a ommand to a key.)
A pre x argument is passed to an intera tive fun tion by typing the
hMETAi key followed by a number, for example, M-3 M-e, or by typing C-
u and then a number, for example, C-u 3 M-e (if you type C-u without a
number, it defaults to 4).

3.3.1 An Intera tive multiply-by-seven


Let's look at the use of the spe ial form intera tive and then at the
fun tion message in the intera tive version of multiply-by-seven. You will
re all that the fun tion de nition looks like this:
(defun multiply-by-seven (number) ; Intera tive version.
"Multiply NUMBER by seven."
(intera tive "p")
(message "The result is %d" (* 7 number)))
In this fun tion, the expression, (intera tive "p"), is a list of two ele-
ments. The "p" tells Ema s to pass the pre x argument to the fun tion and
use its value for the argument of the fun tion.
The argument will be a number. This means that the symbol number
will be bound to a number in the line:
(message "The result is %d" (* 7 number))
For example, if your pre x argument is 5, the Lisp interpreter will evaluate
the line as if it were:
(message "The result is %d" (* 7 5))
(If you are reading this in GNU Ema s, you an evaluate this expression
yourself.) First, the interpreter will evaluate the inner list, whi h is (* 7
5). This returns a value of 35. Next, it will evaluate the outer list, passing
the values of the se ond and subsequent elements of the list to the fun tion
message.
As we have seen, message is an Ema s Lisp fun tion espe ially designed
for sending a one line message to a user. (See Se tion 1.8.5, \The message
fun tion", page 16.) In summary, the message fun tion prints its rst argu-
ment in the e ho area as is, ex ept for o urren es of `%d', `%s', or `% '. When
it sees one of these ontrol sequen es, the fun tion looks to the se ond and
subsequent arguments and prints the value of the argument in the lo ation
in the string where the ontrol sequen e is lo ated.
In the intera tive multiply-by-seven fun tion, the ontrol string is `%d',
whi h requires a number, and the value returned by evaluating (* 7 5) is
the number 35. Consequently, the number 35 is printed in pla e of the `%d'
and the message is `The result is 35'.
(Note that when you all the fun tion multiply-by-seven, the message
is printed without quotes, but when you all message, the text is printed
in double quotes. This is be ause the value returned by message is what
Di erent Options for intera tive 35

appears in the e ho area when you evaluate an expression whose rst element
is message; but when embedded in a fun tion, message prints the text as a
side e e t without quotes.)

3.4 Di erent Options for intera tive


In the example, multiply-by-seven used "p" as the argument to
intera tive. This argument told Ema s to interpret your typing either
C-u followed by a number or hMETAi followed by a number as a ommand
to pass that number to the fun tion as its argument. Ema s has more than
twenty hara ters prede ned for use with intera tive. In almost every
ase, one of these options will enable you to pass the right information in-
tera tively to a fun tion. (See se tion \Code Chara ters for intera tive"
in The GNU Ema s Lisp Referen e Manual.)
For example, the hara ter `r' auses Ema s to pass the beginning and
end of the region (the urrent values of point and mark) to the fun tion as
two separate arguments. It is used as follows:
(intera tive "r")
On the other hand, a `B' tells Ema s to ask for the name of a bu er that
will be passed to the fun tion. When it sees a `B', Ema s will ask for the
name by prompting the user in the minibu er, using a string that follows
the `B', as in "BAppend to buffer: ". Not only will Ema s prompt for the
name, but Ema s will omplete the name if you type enough of it and press
hTABi.
A fun tion with two or more arguments an have information passed
to ea h argument by adding parts to the string that follows intera tive.
When you do this, the information is passed to ea h argument in the same
order it is spe i ed in the intera tive list. In the string, ea h part is
separated from the next part by a `\n', whi h is a newline. For example,
you ould follow "BAppend to buffer: " with a `\n') and an `r'. This would
ause Ema s to pass the values of point and mark to the fun tion as well as
prompt you for the bu er|three arguments in all.
In this ase, the fun tion de nition would look like the following, where
buffer, start, and end are the symbols to whi h intera tive binds the
bu er and the urrent values of the beginning and ending of the region:
(defun name-of-fun tion (buffer start end)
"do umentation..."
(intera tive "BAppend to buffer: \nr")
body-of-fun tion...)
(The spa e after the olon in the prompt makes it look better when you
are prompted. The append-to-buffer fun tion looks exa tly like this. See
Se tion 4.4, \The De nition of append-to-buffer", page 56.)
36 Chapter 3: How To Write Fun tion De nitions

If a fun tion does not have arguments, then intera tive does not require
any. Su h a fun tion ontains the simple expression (intera tive). The
mark-whole-buffer fun tion is like this.
Alternatively, if the spe ial letter- odes are not right for your appli ation,
you an pass your own arguments to intera tive as a list. See se tion
\Using Intera tive" in The GNU Ema s Lisp Referen e Manual, for more
information about this advan ed te hnique.

3.5 Install Code Permanently


When you install a fun tion de nition by evaluating it, it will stay in-
stalled until you quit Ema s. The next time you start a new session of
Ema s, the fun tion will not be installed unless you evaluate the fun tion
de nition again.
At some point, you may want to have ode installed automati ally when-
ever you start a new session of Ema s. There are several ways of doing
this:
 If you have ode that is just for yourself, you an put the ode for the
fun tion de nition in your `.ema s' initialization le. When you start
Ema s, your `.ema s' le is automati ally evaluated and all the fun tion
de nitions within it are installed. See Chapter 16, \Your `.ema s' File",
page 213.
 Alternatively, you an put the fun tion de nitions that you want in-
stalled in one or more les of their own and use the load fun tion to
ause Ema s to evaluate and thereby install ea h of the fun tions in the
les. See Se tion 16.9, \Loading Files", page 222.
 On the other hand, if you have ode that your whole site will use,
it is usual to put it in a le alled `site-init.el' that is loaded when
Ema s is built. This makes the ode available to everyone who uses your
ma hine. (See the `INSTALL' le that is part of the Ema s distribution.)
Finally, if you have ode that everyone who uses Ema s may want, you
an post it on a omputer network or send a opy to the Free Software Foun-
dation. (When you do this, please li ense the ode and its do umentation
under a li ense that permits other people to run, opy, study, modify, and
redistribute the ode and whi h prote ts you from having your work taken
from you.) If you send a opy of your ode to the Free Software Foundation,
and properly prote t yourself and others, it may be in luded in the next
release of Ema s. In large part, this is how Ema s has grown over the past
years, by donations.

3.6 let
The let expression is a spe ial form in Lisp that you will need to use in
most fun tion de nitions.
The Parts of a let Expression 37

let is used to atta h or bind a symbol to a value in su h a way that


the Lisp interpreter will not onfuse the variable with a variable of the same
name that is not part of the fun tion.
To understand why the let spe ial form is ne essary, onsider the situa-
tion in whi h you own a home that you generally refer to as `the house', as
in the senten e, \The house needs painting." If you are visiting a friend and
your host refers to `the house', he is likely to be referring to his house, not
yours, that is, to a di erent house.
If your friend is referring to his house and you think he is referring to
your house, you may be in for some onfusion. The same thing ould happen
in Lisp if a variable that is used inside of one fun tion has the same name
as a variable that is used inside of another fun tion, and the two are not
intended to refer to the same value. The let spe ial form prevents this kind
of onfusion.
The let spe ial form prevents onfusion. let reates a name for a lo al
variable that overshadows any use of the same name outside the let ex-
pression. This is like understanding that whenever your host refers to `the
house', he means his house, not yours. (Symbols used in argument lists work
the same way. See Se tion 3.1, \The defun Spe ial Form", page 29.)
Lo al variables reated by a let expression retain their value only within
the let expression itself (and within expressions alled within the let ex-
pression); the lo al variables have no e e t outside the let expression.
Another way to think about let is that it is like a setq that is temporary
and lo al. The values set by let are automati ally undone when the let is
nished. The setting only e e ts expressions that are inside the bounds of
the let expression. In omputer s ien e jargon, we would say \the binding
of a symbol is visible only in fun tions alled in the let form; in Ema s Lisp,
s oping is dynami , not lexi al."
let an reate more than one variable at on e. Also, let gives ea h
variable it reates an initial value, either a value spe i ed by you, or nil.
(In the jargon, this is alled `binding the variable to the value'.) After let
has reated and bound the variables, it exe utes the ode in the body of the
let, and returns the value of the last expression in the body, as the value of
the whole let expression. (`Exe ute' is a jargon term that means to evaluate
a list; it omes from the use of the word meaning `to give pra ti al e e t to'
(Oxford English Di tionary). Sin e you evaluate an expression to perform
an a tion, `exe ute' has evolved as a synonym to `evaluate'.)

3.6.1 The Parts of a let Expression


A let expression is a list of three parts. The rst part is the symbol
let. The se ond part is a list, alled a varlist, ea h element of whi h is
either a symbol by itself or a two-element list, the rst element of whi h is
a symbol. The third part of the let expression is the body of the let. The
body usually onsists of one or more lists.
38 Chapter 3: How To Write Fun tion De nitions

A template for a let expression looks like this:


(let varlist body ...)

The symbols in the varlist are the variables that are given initial values by
the let spe ial form. Symbols by themselves are given the initial value of
nil; and ea h symbol that is the rst element of a two-element list is bound
to the value that is returned when the Lisp interpreter evaluates the se ond
element.
Thus, a varlist might look like this: (thread (needles 3)). In this ase,
in a let expression, Ema s binds the symbol thread to an initial value of
nil, and binds the symbol needles to an initial value of 3.
When you write a let expression, what you do is put the appropriate
expressions in the slots of the let expression template.
If the varlist is omposed of two-element lists, as is often the ase, the
template for the let expression looks like this:
(let ((variable value )
(variable value )
...)
body ...)

3.6.2 Sample let Expression


The following expression reates and gives initial values to the two vari-
ables zebra and tiger. The body of the let expression is a list whi h alls
the message fun tion.
(let ((zebra 'stripes)
(tiger 'fier e))
(message "One kind of animal has %s and another is %s."
zebra tiger))

Here, the varlist is ((zebra 'stripes) (tiger 'fier e)).


The two variables are zebra and tiger. Ea h variable is the rst element
of a two-element list and ea h value is the se ond element of its two-element
list. In the varlist, Ema s binds the variable zebra to the value stripes, and
binds the variable tiger to the value fier e. In this example, both values
are symbols pre eded by a quote. The values ould just as well have been
another list or a string. The body of the let follows after the list holding the
variables. In this example, the body is a list that uses the message fun tion
to print a string in the e ho area.
The if Spe ial Form 39

You may evaluate the example in the usual fashion, by pla ing the ur-
sor after the last parenthesis and typing C-x C-e. When you do this, the
following will appear in the e ho area:
"One kind of animal has stripes and another is fier e."
As we have seen before, the message fun tion prints its rst argument,
ex ept for `%s'. In this example, the value of the variable zebra is printed
at the lo ation of the rst `%s' and the value of the variable tiger is printed
at the lo ation of the se ond `%s'.

3.6.3 Uninitialized Variables in a let Statement


If you do not bind the variables in a let statement to spe i initial
values, they will automati ally be bound to an initial value of nil, as in the
following expression:
(let ((bir h 3)
pine
fir
(oak 'some))
(message
"Here are %d variables with %s, %s, and %s value."
bir h pine fir oak))
Here, the varlist is ((bir h 3) pine fir (oak 'some)).
If you evaluate this expression in the usual way, the following will appear
in your e ho area:
"Here are 3 variables with nil, nil, and some value."
In this example, Ema s binds the symbol bir h to the number 3, binds the
symbols pine and fir to nil, and binds the symbol oak to the value some.
Note that in the rst part of the let, the variables pine and fir stand
alone as atoms that are not surrounded by parentheses; this is be ause they
are being bound to nil, the empty list. But oak is bound to some and so
is a part of the list (oak 'some). Similarly, bir h is bound to the number
3 and so is in a list with that number. (Sin e a number evaluates to itself,
the number does not need to be quoted. Also, the number is printed in the
message using a `%d' rather than a `%s'.) The four variables as a group are
put into a list to delimit them from the body of the let.

3.7 The if Spe ial Form


A third spe ial form, in addition to defun and let, is the onditional if.
This form is used to instru t the omputer to make de isions. You an write
fun tion de nitions without using if, but it is used often enough, and is
important enough, to be in luded here. It is used, for example, in the ode
for the fun tion beginning-of-buffer.
40 Chapter 3: How To Write Fun tion De nitions

The basi idea behind an if, is that \if a test is true, then an expression
is evaluated." If the test is not true, the expression is not evaluated. For
example, you might make a de ision su h as, \if it is warm and sunny, then
go to the bea h!"
An if expression written in Lisp does not use the word `then'; the test
and the a tion are the se ond and third elements of the list whose rst
element is if. Nonetheless, the test part of an if expression is often alled
the if-part and the se ond argument is often alled the then-part.
Also, when an if expression is written, the true-or-false-test is usually
written on the same line as the symbol if, but the a tion to arry out if the
test is true, the \then-part", is written on the se ond and subsequent lines.
This makes the if expression easier to read.
(if true-or-false-test
a tion-to- arry-out-if-test-is-true )
The true-or-false-test will be an expression that is evaluated by the Lisp
interpreter.
Here is an example that you an evaluate in the usual manner. The test is
whether the number 5 is greater than the number 4. Sin e it is, the message
`5 is greater than 4!' will be printed.
(if (> 5 4) ; if-part
(message "5 is greater than 4!")) ; then-part

(The fun tion > tests whether its rst argument is greater than its se ond
argument and returns true if it is.)
Of ourse, in a tual use, the test in an if expression will not be xed
for all time as it is by the expression (> 5 4). Instead, at least one of the
variables used in the test will be bound to a value that is not known ahead
of time. (If the value were known ahead of time, we would not need to run
the test!)
For example, the value may be bound to an argument of a fun tion de -
nition. In the following fun tion de nition, the hara ter of the animal is a
value that is passed to the fun tion. If the value bound to hara teristi
is fier e, then the message, `It's a tiger!' will be printed; otherwise, nil
will be returned.
(defun type-of-animal ( hara teristi )
"Print message in e ho area depending on CHARACTERISTIC.
If the CHARACTERISTIC is the symbol `fier e',
then warn of a tiger."
(if (equal hara teristi 'fier e)
(message "It's a tiger!")))
The type-of-animal Fun tion in Detail 41

If you are reading this inside of GNU Ema s, you an evaluate the fun tion
de nition in the usual way to install it in Ema s, and then you an evaluate
the following two expressions to see the results:
(type-of-animal 'fier e)

(type-of-animal 'zebra)

When you evaluate (type-of-animal 'fier e), you will see the following
message printed in the e ho area: "It's a tiger!"; and when you evaluate
(type-of-animal 'zebra) you will see nil printed in the e ho area.

3.7.1 The type-of-animal Fun tion in Detail


Let's look at the type-of-animal fun tion in detail.
The fun tion de nition for type-of-animal was written by lling the
slots of two templates, one for a fun tion de nition as a whole, and a se ond
for an if expression.
The template for every fun tion that is not intera tive is:
(defun name-of-fun tion (argument-list)
"do umentation..."
body ...)
The parts of the fun tion that mat h this template look like this:
(defun type-of-animal ( hara teristi )
"Print message in e ho area depending on CHARACTERISTIC.
If the CHARACTERISTIC is the symbol `fier e',
then warn of a tiger."
body: the if expression)
The name of fun tion is type-of-animal; it is passed the value of one
argument. The argument list is followed by a multi-line do umentation
string. The do umentation string is in luded in the example be ause it is a
good habit to write do umentation string for every fun tion de nition. The
body of the fun tion de nition onsists of the if expression.
The template for an if expression looks like this:
(if true-or-false-test
a tion-to- arry-out-if-the-test-returns-true )
In the type-of-animal fun tion, the ode for the if looks like this:
(if (equal hara teristi 'fier e)
(message "It's a tiger!")))
Here, the true-or-false-test is the expression:
(equal hara teristi 'fier e)
In Lisp, equal is a fun tion that determines whether its rst argument is
equal to its se ond argument. The se ond argument is the quoted symbol
42 Chapter 3: How To Write Fun tion De nitions

'fier e and the rst argument is the value of the symbol hara teristi |
in other words, the argument passed to this fun tion.
In the rst exer ise of type-of-animal, the argument fier e is passed to
type-of-animal. Sin e fier e is equal to fier e, the expression, (equal
hara teristi 'fier e), returns a value of true. When this happens, the
if evaluates the se ond argument or then-part of the if: (message "It's
tiger!").
On the other hand, in the se ond exer ise of type-of-animal, the argu-
ment zebra is passed to type-of-animal. zebra is not equal to fier e, so
the then-part is not evaluated and nil is returned by the if expression.

3.8 If{then{else Expressions


An if expression may have an optional third argument, alled the else-
part, for the ase when the true-or-false-test returns false. When this hap-
pens, the se ond argument or then-part of the overall if expression is not
evaluated, but the third or else-part is evaluated. You might think of this
as the loudy day alternative for the de ision `if it is warm and sunny, then
go to the bea h, else read a book!".
The word \else" is not written in the Lisp ode; the else-part of an if
expression omes after the then-part. In the written Lisp, the else-part is
usually written to start on a line of its own and is indented less than the
then-part:
(if true-or-false-test
a tion-to- arry-out-if-the-test-returns-true
a tion-to- arry-out-if-the-test-returns-false )
For example, the following if expression prints the message `4 is not
greater than 5!' when you evaluate it in the usual way:
(if (> 4 5) ; if-part
(message "5 is greater than 4!") ; then-part
(message "4 is not greater than 5!")) ; else-part

Note that the di erent levels of indentation make it easy to distinguish the
then-part from the else-part. (GNU Ema s has several ommands that au-
tomati ally indent if expressions orre tly. See Se tion 1.1.3, \GNU Ema s
Helps You Type Lists", page 3.)
We an extend the type-of-animal fun tion to in lude an else-part by
simply in orporating an additional part to the if expression.
Truth and Falsehood in Ema s Lisp 43

You an see the onsequen es of doing this if you evaluate the following
version of the type-of-animal fun tion de nition to install it and then
evaluate the two subsequent expressions to pass di erent arguments to the
fun tion.
(defun type-of-animal ( hara teristi ) ; Se ond version.
"Print message in e ho area depending on CHARACTERISTIC.
If the CHARACTERISTIC is the symbol `fier e',
then warn of a tiger;
else say it's not fier e."
(if (equal hara teristi 'fier e)
(message "It's a tiger!")
(message "It's not fier e!")))

(type-of-animal 'fier e)

(type-of-animal 'zebra)

When you evaluate (type-of-animal 'fier e), you will see the following
message printed in the e ho area: "It's a tiger!"; but when you evaluate
(type-of-animal 'zebra), you will see "It's not fier e!".
(Of ourse, if the hara teristi were fero ious, the message "It's not
fier e!" would be printed; and it would be misleading! When you write
ode, you need to take into a ount the possibility that some su h argument
will be tested by the if and write your program a ordingly.)

3.9 Truth and Falsehood in Ema s Lisp


There is an important aspe t to the truth test in an if expression. So
far, we have spoken of `true' and `false' as values of predi ates as if they were
new kinds of Ema s Lisp obje ts. In fa t, `false' is just our old friend nil.
Anything else|anything at all|is `true'.
The expression that tests for truth is interpreted as true if the result of
evaluating it is a value that is not nil. In other words, the result of the test
is onsidered true if the value returned is a number su h as 47, a string su h
as "hello", or a symbol (other than nil) su h as flowers, or a list, or even
a bu er!
Before illustrating a test for truth, we need an explanation of nil.
In Ema s Lisp, the symbol nil has two meanings. First, it means the
empty list. Se ond, it means false and is the value returned when a true-or-
false-test tests false. nil an be written as an empty list, (), or as nil. As
far as the Lisp interpreter is on erned, () and nil are the same. Humans,
however, tend to use nil for false and () for the empty list.
In Ema s Lisp, any value that is not nil|is not the empty list|is on-
sidered true. This means that if an evaluation returns something that is not
44 Chapter 3: How To Write Fun tion De nitions

an empty list, an if expression will test true. For example, if a number is


put in the slot for the test, it will be evaluated and will return itself, sin e
that is what numbers do when evaluated. In this onditional, the if expres-
sion will test true. The expression tests false only when nil, an empty list,
is returned by evaluating the expression.
You an see this by evaluating the two expressions in the following ex-
amples.
In the rst example, the number 4 is evaluated as the test in the if
expression and returns itself; onsequently, the then-part of the expression
is evaluated and returned: `true' appears in the e ho area. In the se ond
example, the nil indi ates false; onsequently, the else-part of the expression
is evaluated and returned: `false' appears in the e ho area.
(if 4
'true
'false)
(if nil
'true
'false)
In identally, if some other useful value is not available for a test that
returns true, then the Lisp interpreter will return the symbol t for true. For
example, the expression (> 5 4) returns t when evaluated, as you an see
by evaluating it in the usual way:
(> 5 4)
On the other hand, this fun tion returns nil if the test is false.
(> 4 5)

3.10 save-ex ursion


The save-ex ursion fun tion is the fourth and nal spe ial form that
we will dis uss in this hapter.
In Ema s Lisp programs used for editing, the save-ex ursion fun tion
is very ommon. It saves the lo ation of point and mark, exe utes the body
of the fun tion, and then restores point and mark to their previous positions
if their lo ations were hanged. Its primary purpose is to keep the user from
being surprised and disturbed by unexpe ted movement of point or mark.
Before dis ussing save-ex ursion, however, it may be useful rst to
review what point and mark are in GNU Ema s. Point is the urrent lo ation
of the ursor. Wherever the ursor is, that is point. More pre isely, on
terminals where the ursor appears to be on top of a hara ter, point is
immediately before the hara ter. In Ema s Lisp, point is an integer. The
rst hara ter in a bu er is number one, the se ond is number two, and
so on. The fun tion point returns the urrent position of the ursor as a
number. Ea h bu er has its own value for point.
Template for a save-ex ursion Expression 45

The mark is another position in the bu er; its value an be set with a
ommand su h as C-hSPCi (set-mark- ommand). If a mark has been set, you
an use the ommand C-x C-x (ex hange-point-and-mark) to ause the
ursor to jump to the mark and set the mark to be the previous position
of point. In addition, if you set another mark, the position of the previous
mark is saved in the mark ring. Many mark positions an be saved this way.
You an jump the ursor to a saved mark by typing C-u C-hSPCi one or more
times.
The part of the bu er between point and mark is alled the region. Nu-
merous ommands work on the region, in luding enter-region, ount-
lines-region, kill-region, and print-region.
The save-ex ursion spe ial form saves the lo ations of point and mark
and restores those positions after the ode within the body of the spe ial form
is evaluated by the Lisp interpreter. Thus, if point were in the beginning
of a pie e of text and some ode moved point to the end of the bu er, the
save-ex ursion would put point ba k to where it was before, after the
expressions in the body of the fun tion were evaluated.
In Ema s, a fun tion frequently moves point as part of its internal work-
ings even though a user would not expe t this. For example, ount-lines-
region moves point. To prevent the user from being bothered by jumps that
are both unexpe ted and (from the user's point of view) unne essary, save-
ex ursion is often used to keep point and mark in the lo ation expe ted by
the user. The use of save-ex ursion is good housekeeping.
To make sure the house stays lean, save-ex ursion restores the values
of point and mark even if something goes wrong in the ode inside of it (or,
to be more pre ise and to use the proper jargon, \in ase of abnormal exit").
This feature is very helpful.
In addition to re ording the values of point and mark, save-ex ursion
keeps tra k of the urrent bu er, and restores it, too. This means you an
write ode that will hange the bu er and have save-ex ursion swit h you
ba k to the original bu er. This is how save-ex ursion is used in append-
to-buffer. (See Se tion 4.4, \The De nition of append-to-buffer",
page 56.)
3.10.1 Template for a save-ex ursion Expression
The template for ode using save-ex ursion is simple:
(save-ex ursion
body ...)
The body of the fun tion is one or more expressions that will be evaluated
in sequen e by the Lisp interpreter. If there is more than one expression
in the body, the value of the last one will be returned as the value of the
save-ex ursion fun tion. The other expressions in the body are evaluated
only for their side e e ts; and save-ex ursion itself is used only for its side
e e t (whi h is restoring the positions of point and mark).
46 Chapter 3: How To Write Fun tion De nitions

In more detail, the template for a save-ex ursion expression looks like
this:
(save-ex ursion
rst-expression-in-body
se ond-expression-in-body
third-expression-in-body
...
last-expression-in-body )
An expression, of ourse, may be a symbol on its own or a list.
In Ema s Lisp ode, a save-ex ursion expression often o urs within
the body of a let expression. It looks like this:
(let varlist
(save-ex ursion
body ...))

3.11 Review
In the last few hapters we have introdu ed a fair number of fun tions
and spe ial forms. Here they are des ribed in brief, along with a few similar
fun tions that have not been mentioned yet.
eval-last-sexp
Evaluate the last symboli expression before the urrent lo ation
of point. The value is printed in the e ho area unless the fun tion
is invoked with an argument; in that ase, the output is printed
in the urrent bu er. This ommand is normally bound to C-x
C-e.
defun De ne fun tion. This spe ial form has up to ve parts: the
name, a template for the arguments that will be passed to the
fun tion, do umentation, an optional intera tive de laration,
and the body of the de nition.
For example:
(defun ba k-to-indentation ()
"Move point to first visible hara ter on line."
(intera tive)
(beginning-of-line 1)
(skip- hars-forward " \t"))
intera tive
De lare to the interpreter that the fun tion an be used intera -
tively. This spe ial form may be followed by a string with one
or more parts that pass the information to the arguments of the
fun tion, in sequen e. These parts may also tell the interpreter
to prompt for information. Parts of the string are separated by
newlines, `\n'.
Review 47

Common ode hara ters are:


b The name of an existing bu er.
f The name of an existing le.
p The numeri pre x argument. (Note that this `p' is
lower ase.)
r Point and the mark, as two numeri arguments,
smallest rst. This is the only ode letter that spe -
i es two su essive arguments rather than one.
See se tion \Code Chara ters for `intera tive'" in The GNU
Ema s Lisp Referen e Manual, for a omplete list of ode har-
a ters.
let De lare that a list of variables is for use within the body of the
let and give them an initial value, either nil or a spe i ed
value; then evaluate the rest of the expressions in the body of
the let and return the value of the last one. Inside the body
of the let, the Lisp interpreter does not see the values of the
variables of the same names that are bound outside of the let.
For example,
(let ((foo (buffer-name))
(bar (buffer-size)))
(message
"This buffer is %s and has %d hara ters."
foo bar))

save-ex ursion
Re ord the values of point and mark and the urrent bu er
before evaluating the body of this spe ial form. Restore the
values of point and mark and bu er afterward.
For example,
(message "We are %d hara ters into this buffer."
(- (point)
(save-ex ursion
(goto- har (point-min)) (point))))

if Evaluate the rst argument to the fun tion; if it is true, evaluate


the se ond argument; else evaluate the third argument, if there
is one.
The if spe ial form is alled a onditional. There are other on-
ditionals in Ema s Lisp, but if is perhaps the most ommonly
used.
48 Chapter 3: How To Write Fun tion De nitions

For example,
(if (string-equal
(number-to-string 21)
(substring (ema s-version) 10 12))
(message "This is version 21 Ema s")
(message "This is not version 21 Ema s"))
equal
eq Test whether two obje ts are the same. equal uses one meaning
of the word `same' and eq uses another: equal returns true if
the two obje ts have a similar stru ture and ontents, su h as
two opies of the same book. On the other hand, eq, returns
true if both arguments are a tually the same obje t.
<
>
<=
>= The < fun tion tests whether its rst argument is smaller than
its se ond argument. A orresponding fun tion, >, tests whether
the rst argument is greater than the se ond. Likewise, <= tests
whether the rst argument is less than or equal to the se ond
and >= tests whether the rst argument is greater than or equal
to the se ond. In all ases, both arguments must be numbers or
markers (markers indi ate positions in bu ers).
string<
string-lessp
string=
string-equal
The string-lessp fun tion tests whether its rst argument is
smaller than the se ond argument. A shorter, alternative name
for the same fun tion (a defalias) is string<.
The arguments to string-lessp must be strings or symbols;
the ordering is lexi ographi , so ase is signi ant. The print
names of symbols are used instead of the symbols themselves.
An empty string, `""', a string with no hara ters in it, is smaller
than any string of hara ters.
string-equal provides the orresponding test for equality. Its
shorter, alternative name is string=. There are no string test
fun tions that orrespond to >, >=, or <=.
message Print a message in the e ho area. The rst argument is a string
that an ontain `%s', `%d', or `% ' to print the value of arguments
that follow the string. The argument used by `%s' must be a
string or a symbol; the argument used by `%d' must be a number.
The argument used by `% ' must be an as ii ode number; it will
be printed as the hara ter with that as ii ode.
Review 49

setq
set The setq fun tion sets the value of its rst argument to the
value of the se ond argument. The rst argument is automati-
ally quoted by setq. It does the same for su eeding pairs of
arguments. Another fun tion, set, takes only two arguments
and evaluates both of them before setting the value returned by
its rst argument to the value returned by its se ond argument.
buffer-name
Without an argument, return the name of the bu er, as a string.
buffer-file-name
Without an argument, return the name of the le the bu er is
visiting.
urrent-buffer
Return the bu er in whi h Ema s is a tive; it may not be the
bu er that is visible on the s reen.
other-buffer
Return the most re ently sele ted bu er (other than the bu er
passed to other-buffer as an argument and other than the
urrent bu er).
swit h-to-buffer
Sele t a bu er for Ema s to be a tive in and display it in the
urrent window so users an look at it. Usually bound to C-x b.
set-buffer
Swit h Ema s' attention to a bu er on whi h programs will run.
Don't alter what the window is showing.
buffer-size
Return the number of hara ters in the urrent bu er.
point Return the value of the urrent position of the ursor, as an
integer ounting the number of hara ters from the beginning of
the bu er.
point-min
Return the minimum permissible value of point in the urrent
bu er. This is 1, unless narrowing is in e e t.
point-max
Return the value of the maximum permissible value of point in
the urrent bu er. This is the end of the bu er, unless narrowing
is in e e t.
50 Chapter 3: How To Write Fun tion De nitions

3.12 Exer ises


 Write a non-intera tive fun tion that doubles the value of its argument,
a number. Make that fun tion intera tive.
 Write a fun tion that tests whether the urrent value of fill- olumn
is greater than the argument passed to the fun tion, and if so, prints an
appropriate message.
Finding More Information 51

4 A Few Bu er{Related Fun tions


In this hapter we study in detail several of the fun tions used in GNU
Ema s. This is alled a \walk-through". These fun tions are used as ex-
amples of Lisp ode, but are not imaginary examples; with the ex eption of
the rst, simpli ed fun tion de nition, these fun tions show the a tual ode
used in GNU Ema s. You an learn a great deal from these de nitions. The
fun tions des ribed here are all related to bu ers. Later, we will study other
fun tions.

4.1 Finding More Information


In this walk-through, I will des ribe ea h new fun tion as we ome to it,
sometimes in detail and sometimes brie y. If you are interested, you an get
the full do umentation of any Ema s Lisp fun tion at any time by typing
C-h f and then the name of the fun tion (and then hRETi). Similarly, you
an get the full do umentation for a variable by typing C-h v and then the
name of the variable (and then hRETi).
In versions 20 and higher, when a fun tion is written in Ema s Lisp,
des ribe-fun tion will also tell you the lo ation of the fun tion de nition.
If you move point over the le name and press the hRETi key, whi h is this
ase means help-follow rather than `return' or `enter', Ema s will take you
dire tly to the fun tion de nition.
More generally, if you want to see a fun tion in its original sour e le,
you an use the find-tags fun tion to jump to it. find-tags works with
a wide variety of languages, not just Lisp, and C, and it works with non-
programming text as well. For example, find-tags will jump to the various
nodes in the Texinfo sour e le of this do ument.
The find-tags fun tion depends on `tags tables' that re ord the lo ations
of the fun tions, variables, and other items to whi h find-tags jumps.
To use the find-tags ommand, type M-. (i.e., type the hMETAi key and
the period key at the same time, or else type the hESCi key and then type
the period key), and then, at the prompt, type in the name of the fun tion
whose sour e ode you want to see, su h as mark-whole-buffer, and then
type hRETi. Ema s will swit h bu ers and display the sour e ode for the
fun tion on your s reen. To swit h ba k to your urrent bu er, type C-x b
hRETi. (On some keyboards, the hMETAi key is labelled hALTi.)
Depending on how the initial default values of your opy of Ema s are
set, you may also need to spe ify the lo ation of your `tags table', whi h
is a le alled `TAGS'. For example, if you are interested in Ema s sour es,
the tags table you will most likely want, if it has already been reated for
you, will be in a subdire tory of the `/usr/lo al/share/ema s/' dire -
tory; thus you would use the M-x visit-tags-table ommand and spe -
ify a pathname su h as `/usr/lo al/share/ema s/21.0.100/lisp/TAGS'
52 Chapter 4: A Few Bu er{Related Fun tions

or `/usr/lo al/sr /ema s/lisp/TAGS'. If the tags table has not already
been reated, you will have to reate it yourself.
To reate a `TAGS' le in a spe i dire tory, swit h to that dire tory
in Ema s using M-x d ommand, or list the dire tory with C-x d (dired).
Then run the ompile ommand, with etags *.el as the ommand to exe-
ute
M-x ompile RET etags *.el RET
For more information, see Se tion 12.5, \Create Your Own `TAGS' File",
page 163.
After you be ome more familiar with Ema s Lisp, you will nd that you
will frequently use find-tags to navigate your way around sour e ode; and
you will reate your own `TAGS' tables.
In identally, the les that ontain Lisp ode are onventionally alled
libraries. The metaphor is derived from that of a spe ialized library, su h as
a law library or an engineering library, rather than a general library. Ea h
library, or le, ontains fun tions that relate to a parti ular topi or a tivity,
su h as `abbrev.el' for handling abbreviations and other typing short uts,
and `help.el' for on-line help. (Sometimes several libraries provide ode
for a single a tivity, as the various `rmail...' les provide ode for reading
ele troni mail.) In The GNU Ema s Manual, you will see senten es su h as
\The C-h p ommand lets you sear h the standard Ema s Lisp libraries by
topi keywords."

4.2 A Simpli ed beginning-of-buffer De nition


The beginning-of-buffer ommand is a good fun tion to start with
sin e you are likely to be familiar with it and it is easy to understand. Used
as an intera tive ommand, beginning-of-buffer moves the ursor to the
beginning of the bu er, leaving the mark at the previous position. It is
generally bound to M-<.
In this se tion, we will dis uss a shortened version of the fun tion that
shows how it is most frequently used. This shortened fun tion works as
written, but it does not ontain the ode for a omplex option. In another
se tion, we will des ribe the entire fun tion. (See Se tion 5.3, \Complete
De nition of beginning-of-buffer", page 69.)
Before looking at the ode, let's onsider what the fun tion de nition has
to ontain: it must in lude an expression that makes the fun tion intera tive
so it an be alled by typing M-x beginning-of-buffer or by typing a
key hord su h as C-<; it must in lude ode to leave a mark at the original
position in the bu er; and it must in lude ode to move the ursor to the
beginning of the bu er.
A Simpli ed beginning-of-buffer De nition 53

Here is the omplete text of the shortened version of the fun tion:
(defun simplified-beginning-of-buffer ()
"Move point to the beginning of the buffer;
leave mark at previous position."
(intera tive)
(push-mark)
(goto- har (point-min)))
Like all fun tion de nitions, this de nition has ve parts following the
spe ial form defun:
1. The name: in this example, simplified-beginning-of-buffer.
2. A list of the arguments: in this example, an empty list, (),
3. The do umentation string.
4. The intera tive expression.
5. The body.
In this fun tion de nition, the argument list is empty; this means that this
fun tion does not require any arguments. (When we look at the de nition
for the omplete fun tion, we will see that it may be passed an optional
argument.)
The intera tive expression tells Ema s that the fun tion is intended to be
used intera tively. In this example, intera tive does not have an argument
be ause simplified-beginning-of-buffer does not require one.
The body of the fun tion onsists of the two lines:
(push-mark)
(goto- har (point-min))
The rst of these lines is the expression, (push-mark). When this ex-
pression is evaluated by the Lisp interpreter, it sets a mark at the urrent
position of the ursor, wherever that may be. The position of this mark is
saved in the mark ring.
The next line is (goto- har (point-min)). This expression jumps the
ursor to the minimum point in the bu er, that is, to the beginning of the
bu er (or to the beginning of the a essible portion of the bu er if it is
narrowed. See Chapter 6, \Narrowing and Widening", page 77.)
The push-mark ommand sets a mark at the pla e where the ursor was
lo ated before it was moved to the beginning of the bu er by the (goto-
har (point-min)) expression. Consequently, you an, if you wish, go ba k
to where you were originally by typing C-x C-x.
That is all there is to the fun tion de nition!
When you are reading ode su h as this and ome upon an unfamiliar
fun tion, su h as goto- har, you an nd out what it does by using the
des ribe-fun tion ommand. To use this ommand, type C-h f and then
type in the name of the fun tion and press hRETi. The des ribe-fun tion
54 Chapter 4: A Few Bu er{Related Fun tions

ommand will print the fun tion's do umentation string in a `*Help*' win-
dow. For example, the do umentation for goto- har is:
One arg, a number. Set point to that number.
Beginning of buffer is position (point-min),
end is (point-max).
(The prompt for des ribe-fun tion will o er you the symbol under or
pre eding the ursor, so you an save typing by positioning the ursor right
over or after the fun tion and then typing C-h f hRETi.)
The end-of-buffer fun tion de nition is written in the same way as
the beginning-of-buffer de nition ex ept that the body of the fun tion
ontains the expression (goto- har (point-max)) in pla e of (goto- har
(point-min)).

4.3 The De nition of mark-whole-buffer


The mark-whole-buffer fun tion is no harder to understand than the
simplified-beginning-of-buffer fun tion. In this ase, however, we will
look at the omplete fun tion, not a shortened version.
The mark-whole-buffer fun tion is not as ommonly used as the
beginning-of-buffer fun tion, but is useful nonetheless: it marks a whole
bu er as a region by putting point at the beginning and a mark at the end
of the bu er. It is generally bound to C-x h.
In GNU Ema s 20, the ode for the omplete fun tion looks like this:
(defun mark-whole-buffer ()
"Put point at beginning and mark at end of buffer."
(intera tive)
(push-mark (point))
(push-mark (point-max))
(goto- har (point-min)))
Like all other fun tions, the mark-whole-buffer fun tion ts into the
template for a fun tion de nition. The template looks like this:
(defun name-of-fun tion (argument-list)
"do umentation..."
(intera tive-expression...)
body ...)
Here is how the fun tion works: the name of the fun tion is mark-whole-
buffer; it is followed by an empty argument list, `()', whi h means that the
fun tion does not require arguments. The do umentation omes next.
The next line is an (intera tive) expression that tells Ema s that
the fun tion will be used intera tively. These details are similar to the
simplified-beginning-of-buffer fun tion des ribed in the previous se -
tion.
Body of mark-whole-buffer 55

4.3.1 Body of mark-whole-buffer


The body of the mark-whole-buffer fun tion onsists of three lines of
ode:
(push-mark (point))
(push-mark (point-max))
(goto- har (point-min))
The rst of these lines is the expression, (push-mark (point)).
This line does exa tly the same job as the rst line of the body of
the simplified-beginning-of-buffer fun tion, whi h is written (push-
mark). In both ases, the Lisp interpreter sets a mark at the urrent position
of the ursor.
I don't know why the expression in mark-whole-buffer is written (push-
mark (point)) and the expression in beginning-of-buffer is written
(push-mark). Perhaps whoever wrote the ode did not know that the ar-
guments for push-mark are optional and that if push-mark is not passed an
argument, the fun tion automati ally sets mark at the lo ation of point by
default. Or perhaps the expression was written so as to parallel the stru -
ture of the next line. In any ase, the line auses Ema s to determine the
position of point and set a mark there.
The next line of mark-whole-buffer is (push-mark (point-max). This
expression sets a mark at the point in the bu er that has the highest number.
This will be the end of the bu er (or, if the bu er is narrowed, the end of the
a essible portion of the bu er. See Chapter 6, \Narrowing and Widening",
page 77, for more about narrowing.) After this mark has been set, the
previous mark, the one set at point, is no longer set, but Ema s remembers
its position, just as all other re ent marks are always remembered. This
means that you an, if you wish, go ba k to that position by typing C-u
C-hSPCi twi e.
(In GNU Ema s 21, the (push-mark (point-max) is slightly more om-
pli ated than shown here. The line reads
(push-mark (point-max) nil t)
(The expression works nearly the same as before. It sets a mark at the
highest numbered pla e in the bu er that it an. However, in this version,
push-mark has two additional arguments. The se ond argument to push-
mark is nil. This tells the fun tion it should display a message that says
`Mark set' when it pushes the mark. The third argument is t. This tells
push-mark to a tivate the mark when Transient Mark mode is turned on.
Transient Mark mode highlights the urrently a tive region. It is usually
turned o .)
Finally, the last line of the fun tion is (goto- har (point-min))). This
is written exa tly the same way as it is written in beginning-of-buffer.
The expression moves the ursor to the minimum point in the bu er, that is,
to the beginning of the bu er (or to the beginning of the a essible portion
56 Chapter 4: A Few Bu er{Related Fun tions

of the bu er). As a result of this, point is pla ed at the beginning of the


bu er and mark is set at the end of the bu er. The whole bu er is, therefore,
the region.

4.4 The De nition of append-to-buffer


The append-to-buffer ommand is very nearly as simple as the mark-
whole-buffer ommand. What it does is opy the region (that is, the part
of the bu er between point and mark) from the urrent bu er to a spe i ed
bu er.
The append-to-buffer ommand uses the insert-buffer-substring
fun tion to opy the region. insert-buffer-substring is des ribed by its
name: it takes a string of hara ters from part of a bu er, a \substring", and
inserts them into another bu er. Most of append-to-buffer is on erned
with setting up the onditions for insert-buffer-substring to work: the
ode must spe ify both the bu er to whi h the text will go and the region
that will be opied. Here is the omplete text of the fun tion:
(defun append-to-buffer (buffer start end)
"Append to spe ified buffer the text of the region.
It is inserted into that buffer before its point.
When alling from a program, give three arguments:
a buffer or the name of one, and two hara ter numbers
spe ifying the portion of the urrent buffer to be opied."
(intera tive "BAppend to buffer: \nr")
(let ((oldbuf ( urrent-buffer)))
(save-ex ursion
(set-buffer (get-buffer- reate buffer))
(insert-buffer-substring oldbuf start end))))
The fun tion an be understood by looking at it as a series of lled-in
templates.
The outermost template is for the fun tion de nition. In this fun tion,
it looks like this (with several slots lled in):
(defun append-to-buffer (buffer start end)
"do umentation..."
(intera tive "BAppend to buffer: \nr")
body ...)
The rst line of the fun tion in ludes its name and three arguments. The
arguments are the buffer to whi h the text will be opied, and the start
and end of the region in the urrent bu er that will be opied.
The next part of the fun tion is the do umentation, whi h is lear and
omplete.
The Body of append-to-buffer 57

4.4.1 The append-to-buffer Intera tive Expression


Sin e the append-to-buffer fun tion will be used intera tively, the fun -
tion must have an intera tive expression. (For a review of intera tive,
see Se tion 3.3, \Making a Fun tion Intera tive", page 33.) The expression
reads as follows:
(intera tive "BAppend to buffer: \nr")
This expression has an argument inside of quotation marks and that argu-
ment has two parts, separated by `\n'.
The rst part is `BAppend to buffer: '. Here, the `B' tells Ema s to ask
for the name of the bu er that will be passed to the fun tion. Ema s will
ask for the name by prompting the user in the minibu er, using the string
following the `B', whi h is the string `Append to buffer: '. Ema s then
binds the variable buffer in the fun tion's argument list to the spe i ed
bu er.
The newline, `\n', separates the rst part of the argument from the se ond
part. It is followed by an `r' that tells Ema s to bind the two arguments
that follow the symbol buffer in the fun tion's argument list (that is, start
and end) to the values of point and mark.

4.4.2 The Body of append-to-buffer


The body of the append-to-buffer fun tion begins with let.
As we have seen before (see Se tion 3.6, \let", page 36), the purpose of
a let expression is to reate and give initial values to one or more variables
that will only be used within the body of the let. This means that su h
a variable will not be onfused with any variable of the same name outside
the let expression.
We an see how the let expression ts into the fun tion as a whole
by showing a template for append-to-buffer with the let expression in
outline:
(defun append-to-buffer (buffer start end)
"do umentation..."
(intera tive "BAppend to buffer: \nr")
(let ((variable value ))
body ...)
The let expression has three elements:
1. The symbol let;
2. A varlist ontaining, in this ase, a single two-element list, (variable
value );
3. The body of the let expression.
58 Chapter 4: A Few Bu er{Related Fun tions

In the append-to-buffer fun tion, the varlist looks like this:


(oldbuf ( urrent-buffer))

In this part of the let expression, the one variable, oldbuf, is bound to the
value returned by the ( urrent-buffer) expression. The variable, oldbuf,
is used to keep tra k of the bu er in whi h you are working and from whi h
you will opy.
The element or elements of a varlist are surrounded by a set of parentheses
so the Lisp interpreter an distinguish the varlist from the body of the let.
As a onsequen e, the two-element list within the varlist is surrounded by a
ir ums ribing set of parentheses. The line looks like this:
(let ((oldbuf ( urrent-buffer)))
... )

The two parentheses before oldbuf might surprise you if you did not realize
that the rst parenthesis before oldbuf marks the boundary of the varlist
and the se ond parenthesis marks the beginning of the two-element list,
(oldbuf ( urrent-buffer)).

4.4.3 save-ex ursion in append-to-buffer


The body of the let expression in append-to-buffer onsists of a save-
ex ursion expression.
The save-ex ursion fun tion saves the lo ations of point and mark,
and restores them to those positions after the expressions in the body of the
save-ex ursion omplete exe ution. In addition, save-ex ursion keeps
tra k of the original bu er, and restores it. This is how save-ex ursion is
used in append-to-buffer.
In identally, it is worth noting here that a Lisp fun tion is normally for-
matted so that everything that is en losed in a multi-line spread is indented
more to the right than the rst symbol. In this fun tion de nition, the let
is indented more than the defun, and the save-ex ursion is indented more
than the let, like this:
(defun ...
...
...
(let...
(save-ex ursion
...
save-ex ursion in append-to-buffer 59

This formatting onvention makes it easy to see that the two lines in the
body of the save-ex ursion are en losed by the parentheses asso iated
with save-ex ursion, just as the save-ex ursion itself is en losed by the
parentheses asso iated with the let:
(let ((oldbuf ( urrent-buffer)))
(save-ex ursion
(set-buffer (get-buffer- reate buffer))
(insert-buffer-substring oldbuf start end))))
The use of the save-ex ursion fun tion an be viewed as a pro ess of
lling in the slots of a template:
(save-ex ursion
rst-expression-in-body
se ond-expression-in-body
...
last-expression-in-body )
In this fun tion, the body of the save-ex ursion ontains only two expres-
sions. The body looks like this:
(set-buffer (get-buffer- reate buffer))
(insert-buffer-substring oldbuf start end)
When the append-to-buffer fun tion is evaluated, the two expressions
in the body of the save-ex ursion are evaluated in sequen e. The value of
the last expression is returned as the value of the save-ex ursion fun tion;
the other expression is evaluated only for its side e e ts.
The rst line in the body of the save-ex ursion uses the set-buffer
fun tion to hange the urrent bu er to the one spe i ed in the rst argument
to append-to-buffer. (Changing the bu er is the side e e t; as we have
said before, in Lisp, a side e e t is often the primary thing we want.) The
se ond line does the primary work of the fun tion.
The set-buffer fun tion hanges Ema s' attention to the bu er to whi h
the text will be opied and from whi h save-ex ursion will return.
The line looks like this:
(set-buffer (get-buffer- reate buffer))
The innermost expression of this list is (get-buffer- reate buffer).
This expression uses the get-buffer- reate fun tion, whi h either gets the
named bu er, or if it does not exist, reates one with the given name. This
means you an use append-to-buffer to put text into a bu er that did not
previously exist.
get-buffer- reate also keeps set-buffer from getting an unne essary
error: set-buffer needs a bu er to go to; if you were to spe ify a bu er that
does not exist, Ema s would baulk. Sin e get-buffer- reate will reate a
bu er if none exists, set-buffer is always provided with a bu er.
60 Chapter 4: A Few Bu er{Related Fun tions

The last line of append-to-buffer does the work of appending the text:
(insert-buffer-substring oldbuf start end)
The insert-buffer-substring fun tion opies a string from the bu er
spe i ed as its rst argument and inserts the string into the present bu er.
In this ase, the argument to insert-buffer-substring is the value of the
variable reated and bound by the let, namely the value of oldbuf, whi h
was the urrent bu er when you gave the append-to-buffer ommand.
After insert-buffer-substring has done its work, save-ex ursion
will restore the a tion to the original bu er and append-to-buffer will
have done its job.
Written in skeletal form, the workings of the body look like this:
(let (bind-oldbuf-to-value-of- urrent-buffer)
(save-ex ursion ; Keep tra k of bu er.
hange-bu er
insert-substring-from-oldbuf-into-bu er )

hange-ba k-to-original-bu er-when- nished


let-the-lo al-meaning-of-oldbuf-disappear-when- nished

In summary, append-to-buffer works as follows: it saves the value of the


urrent bu er in the variable alled oldbuf. It gets the new bu er, reating
one if need be, and swit hes Ema s to it. Using the value of oldbuf, it
inserts the region of text from the old bu er into the new bu er; and then
using save-ex ursion, it brings you ba k to your original bu er.
In looking at append-to-buffer, you have explored a fairly omplex
fun tion. It shows how to use let and save-ex ursion, and how to hange
to and ome ba k from another bu er. Many fun tion de nitions use let,
save-ex ursion, and set-buffer this way.

4.5 Review
Here is a brief summary of the various fun tions dis ussed in this hapter.
des ribe-fun tion
des ribe-variable
Print the do umentation for a fun tion or variable. Convention-
ally bound to C-h f and C-h v.
find-tag Find the le ontaining the sour e for a fun tion or variable and
swit h bu ers to it, positioning point at the beginning of the
item. Conventionally bound to M-. (that's a period following
the hMETAi key).
Exer ises 61

save-ex ursion
Save the lo ation of point and mark and restore their values after
the arguments to save-ex ursion have been evaluated. Also,
remember the urrent bu er and return to it.
push-mark
Set mark at a lo ation and re ord the value of the previous mark
on the mark ring. The mark is a lo ation in the bu er that will
keep its relative position even if text is added to or removed
from the bu er.
goto- har
Set point to the lo ation spe i ed by the value of the argument,
whi h an be a number, a marker, or an expression that returns
the number of a position, su h as (point-min).
insert-buffer-substring
Copy a region of text from a bu er that is passed to the fun tion
as an argument and insert the region into the urrent bu er.
mark-whole-buffer
Mark the whole bu er as a region. Normally bound to C-x h.
set-buffer
Swit h the attention of Ema s to another bu er, but do not
hange the window being displayed. Used when the program
rather than a human is to work on a di erent bu er.
get-buffer- reate
get-buffer
Find a named bu er or reate one if a bu er of that name does
not exist. The get-buffer fun tion returns nil if the named
bu er does not exist.

4.6 Exer ises


 Write your own simplified-end-of-buffer fun tion de nition; then
test it to see whether it works.
 Use if and get-buffer to write a fun tion that prints a message telling
you whether a bu er exists.
 Using find-tag, nd the sour e for the opy-to-buffer fun tion.
62 Chapter 4: A Few Bu er{Related Fun tions
The De nition of opy-to-buffer 63

5 A Few More Complex Fun tions


In this hapter, we build on what we have learned in previous hapters by
looking at more omplex fun tions. The opy-to-buffer fun tion illustrates
use of two save-ex ursion expressions in one de nition, while the insert-
buffer fun tion illustrates use of an asterisk in an intera tive expression,
use of or, and the important distin tion between a name and the obje t to
whi h the name refers.

5.1 The De nition of opy-to-buffer


After understanding how append-to-buffer works, it is easy to under-
stand opy-to-buffer. This fun tion opies text into a bu er, but in-
stead of adding to the se ond bu er, it repla es the previous text in the
se ond bu er. The ode for the opy-to-buffer fun tion is almost the
same as the ode for append-to-buffer, ex ept that erase-buffer and
a se ond save-ex ursion are used. (See Se tion 4.4, \The De nition of
append-to-buffer", page 56, for the des ription of append-to-buffer.)
The body of opy-to-buffer looks like this
...
(intera tive "BCopy to buffer: \nr")
(let ((oldbuf ( urrent-buffer)))
(save-ex ursion
(set-buffer (get-buffer- reate buffer))
(erase-buffer)
(save-ex ursion
(insert-buffer-substring oldbuf start end)))))
This ode is similar to the ode in append-to-buffer: it is only after
hanging to the bu er to whi h the text will be opied that the de nition
for this fun tion diverges from the de nition for append-to-buffer: the
opy-to-buffer fun tion erases the bu er's former ontents. (This is what
is meant by `repla ement'; to repla e text, Ema s erases the previous text
and then inserts new text.) After erasing the previous ontents of the bu er,
save-ex ursion is used for a se ond time and the new text is inserted.
Why is save-ex ursion used twi e? Consider again what the fun tion
does.
In outline, the body of opy-to-buffer looks like this:
(let (bind-oldbuf-to-value-of- urrent-buffer)
(save-ex ursion ; First use of save-ex ursion.
hange-bu er
(erase-buffer)
(save-ex ursion ; Se ond use of save-ex ursion.
insert-substring-from-oldbuf-into-bu er )))
64 Chapter 5: A Few More Complex Fun tions

The rst use of save-ex ursion returns Ema s to the bu er from whi h
the text is being opied. That is lear, and is just like its use in append-
to-buffer. Why the se ond use? The reason is that insert-buffer-
substring always leaves point at the end of the region being inserted. The
se ond save-ex ursion auses Ema s to leave point at the beginning of the
text being inserted. In most ir umstan es, users prefer to nd point at the
beginning of inserted text. (Of ourse, the opy-to-buffer fun tion returns
the user to the original bu er when done|but if the user then swit hes to
the opied-to bu er, point will go to the beginning of the text. Thus, this
use of a se ond save-ex ursion is a little ni ety.)

5.2 The De nition of insert-buffer


insert-buffer is yet another bu er-related fun tion. This ommand
opies another bu er into the urrent bu er. It is the reverse of append-
to-buffer or opy-to-buffer, sin e they opy a region of text from the
urrent bu er to another bu er.
In addition, this ode illustrates the use of intera tive with a bu er
that might be read-only and the important distin tion between the name of
an obje t and the obje t a tually referred to.
Here is the ode:
(defun insert-buffer (buffer)
"Insert after point the ontents of BUFFER.
Puts mark after the inserted text.
BUFFER may be a buffer or a buffer name."
(intera tive "*bInsert buffer: ")
(or (bufferp buffer)
(setq buffer (get-buffer buffer)))
(let (start end newmark)
(save-ex ursion
(save-ex ursion
(set-buffer buffer)
(setq start (point-min) end (point-max)))
(insert-buffer-substring buffer start end)
(setq newmark (point)))
(push-mark newmark)))
As with other fun tion de nitions, you an use a template to see an
outline of the fun tion:
(defun insert-buffer (buffer)
"do umentation..."
(intera tive "*bInsert buffer: ")
body ...)
The Body of the insert-buffer Fun tion 65

5.2.1 The Intera tive Expression in insert-buffer


In insert-buffer, the argument to the intera tive de laration has
two parts, an asterisk, `*', and `bInsert buffer: '.

A Read-only Bu er
The asterisk is for the situation when the bu er is a read-only bu er|
a bu er that annot be modi ed. If insert-buffer is alled on a bu er
that is read-only, a message to this e e t is printed in the e ho area and
the terminal may beep or blink at you; you will not be permitted to insert
anything into urrent bu er. The asterisk does not need to be followed by a
newline to separate it from the next argument.

`b' in an Intera tive Expression


The next argument in the intera tive expression starts with a lower ase
`b'. (This is di erent from the ode for append-to-buffer, whi h uses an
upper- ase `B'. See Se tion 4.4, \The De nition of append-to-buffer",
page 56.) The lower- ase `b' tells the Lisp interpreter that the argument for
insert-buffer should be an existing bu er or else its name. (The upper-
ase `B' option provides for the possibility that the bu er does not exist.)
Ema s will prompt you for the name of the bu er, o ering you a default
bu er, with name ompletion enabled. If the bu er does not exist, you
re eive a message that says \No mat h"; your terminal may beep at you as
well.

5.2.2 The Body of the insert-buffer Fun tion


The body of the insert-buffer fun tion has two major parts: an or
expression and a let expression. The purpose of the or expression is to
ensure that the argument buffer is bound to a bu er and not just the name
of a bu er. The body of the let expression ontains the ode whi h opies
the other bu er into the urrent bu er.
In outline, the two expressions t into the insert-buffer fun tion like
this:
(defun insert-buffer (buffer)
"do umentation..."
(intera tive "*bInsert buffer: ")
(or ...
...
(let (varlist)
body-of-let... )
66 Chapter 5: A Few More Complex Fun tions

To understand how the or expression ensures that the argument buffer


is bound to a bu er and not to the name of a bu er, it is rst ne essary to
understand the or fun tion.
Before doing this, let me rewrite this part of the fun tion using if so that
you an see what is done in a manner that will be familiar.

5.2.3 insert-buffer With an if Instead of an or


The job to be done is to make sure the value of buffer is a bu er itself
and not the name of a bu er. If the value is the name, then the bu er itself
must be got.
You an imagine yourself at a onferen e where an usher is wandering
around holding a list with your name on it and looking for you: the usher is
\bound" to your name, not to you; but when the usher nds you and takes
your arm, the usher be omes \bound" to you.
In Lisp, you might des ribe this situation like this:
(if (not (holding-on-to-guest))
(find-and-take-arm-of-guest))
We want to do the same thing with a bu er|if we do not have the bu er
itself, we want to get it.
Using a predi ate alled bufferp that tells us whether we have a bu er
(rather than its name), we an write the ode like this:
(if (not (bufferp buffer)) ; if-part
(setq buffer (get-buffer buffer))) ; then-part
Here, the true-or-false-test of the if expression is (not (bufferp buffer));
and the then-part is the expression (setq buffer (get-buffer buffer)).
In the test, the fun tion bufferp returns true if its argument is a bu er|
but false if its argument is the name of the bu er. (The last hara ter of
the fun tion name bufferp is the hara ter `p'; as we saw earlier, su h use
of `p' is a onvention that indi ates that the fun tion is a predi ate, whi h is
a term that means that the fun tion will determine whether some property
is true or false. See Se tion 1.8.4, \Using the Wrong Type Obje t as an
Argument", page 14.)
The fun tion not pre edes the expression (bufferp buffer), so the true-
or-false-test looks like this:
(not (bufferp buffer))
not is a fun tion that returns true if its argument is false and false if its
argument is true. So if (bufferp buffer) returns true, the not expression
returns false and vi e-versa: what is \not true" is false and what is \not
false" is true.
Using this test, the if expression works as follows: when the value of
the variable buffer is a tually a bu er rather then its name, the true-or-
false-test returns false and the if expression does not evaluate the then-part.
The or in the Body 67

This is ne, sin e we do not need to do anything to the variable buffer if it


really is a bu er.
On the other hand, when the value of buffer is not a bu er itself, but
the name of a bu er, the true-or-false-test returns true and the then-part
of the expression is evaluated. In this ase, the then-part is (setq buffer
(get-buffer buffer)). This expression uses the get-buffer fun tion to
return an a tual bu er itself, given its name. The setq then sets the variable
buffer to the value of the bu er itself, repla ing its previous value (whi h
was the name of the bu er).

5.2.4 The or in the Body


The purpose of the or expression in the insert-buffer fun tion is to
ensure that the argument buffer is bound to a bu er and not just to the
name of a bu er. The previous se tion shows how the job ould have been
done using an if expression. However, the insert-buffer fun tion a tually
uses or. To understand this, it is ne essary to understand how or works.
An or fun tion an have any number of arguments. It evaluates ea h
argument in turn and returns the value of the rst of its arguments that is
not nil. Also, and this is a ru ial feature of or, it does not evaluate any
subsequent arguments after returning the rst non-nil value.
The or expression looks like this:
(or (bufferp buffer)
(setq buffer (get-buffer buffer)))

The rst argument to or is the expression (bufferp buffer). This expres-


sion returns true (a non-nil value) if the bu er is a tually a bu er, and
not just the name of a bu er. In the or expression, if this is the ase,
the or expression returns this true value and does not evaluate the next
expression|and this is ne with us, sin e we do not want to do anything to
the value of buffer if it really is a bu er.
On the other hand, if the value of (bufferp buffer) is nil, whi h it will
be if the value of buffer is the name of a bu er, the Lisp interpreter evaluates
the next element of the or expression. This is the expression (setq buffer
(get-buffer buffer)). This expression returns a non-nil value, whi h is
the value to whi h it sets the variable buffer|and this value is a bu er
itself, not the name of a bu er.
The result of all this is that the symbol buffer is always bound to a bu er
itself rather than to the name of a bu er. All this is ne essary be ause the
set-buffer fun tion in a following line only works with a bu er itself, not
with the name to a bu er.
68 Chapter 5: A Few More Complex Fun tions

In identally, using or, the situation with the usher would be written like
this:
(or (holding-on-to-guest) (find-and-take-arm-of-guest))

5.2.5 The let Expression in insert-buffer


After ensuring that the variable buffer refers to a bu er itself and not
just to the name of a bu er, the insert-buffer fun tion ontinues with a
let expression. This spe i es three lo al variables, start, end, and newmark
and binds them to the initial value nil. These variables are used inside the
remainder of the let and temporarily hide any other o urren e of variables
of the same name in Ema s until the end of the let.
The body of the let ontains two save-ex ursion expressions. First, we
will look at the inner save-ex ursion expression in detail. The expression
looks like this:
(save-ex ursion
(set-buffer buffer)
(setq start (point-min) end (point-max)))
The expression (set-buffer buffer) hanges Ema s' attention from the
urrent bu er to the one from whi h the text will opied. In that bu er,
the variables start and end are set to the beginning and end of the bu er,
using the ommands point-min and point-max. Note that we have here an
illustration of how setq is able to set two variables in the same expression.
The rst argument of setq is set to the value of its se ond, and its third
argument is set to the value of its fourth.
After the body of the inner save-ex ursion is evaluated, the save-
ex ursion restores the original bu er, but start and end remain set to the
values of the beginning and end of the bu er from whi h the text will be
opied.
The outer save-ex ursion expression looks like this:
(save-ex ursion
(inner-save-ex ursion-expression
(go-to-new-bu er-and-set-start-and-end)
(insert-buffer-substring buffer start end)
(setq newmark (point)))
The insert-buffer-substring fun tion opies the text into the urrent
bu er from the region indi ated by start and end in buffer. Sin e the
whole of the se ond bu er lies between start and end, the whole of the
se ond bu er is opied into the bu er you are editing. Next, the value of
point, whi h will be at the end of the inserted text, is re orded in the variable
newmark.
After the body of the outer save-ex ursion is evaluated, point and mark
are relo ated to their original pla es.
Optional Arguments 69

However, it is onvenient to lo ate a mark at the end of the newly inserted


text and lo ate point at its beginning. The newmark variable re ords the end
of the inserted text. In the last line of the let expression, the (push-mark
newmark) expression fun tion sets a mark to this lo ation. (The previous
lo ation of the mark is still a essible; it is re orded on the mark ring and
you an go ba k to it with C-u C-hSPCi.) Meanwhile, point is lo ated at the
beginning of the inserted text, whi h is where it was before you alled the
insert fun tion.
The whole let expression looks like this:
(let (start end newmark)
(save-ex ursion
(save-ex ursion
(set-buffer buffer)
(setq start (point-min) end (point-max)))
(insert-buffer-substring buffer start end)
(setq newmark (point)))
(push-mark newmark))

Like the append-to-buffer fun tion, the insert-buffer fun tion uses
let, save-ex ursion, and set-buffer. In addition, the fun tion illustrates
one way to use or. All these fun tions are building blo ks that we will nd
and use again and again.

5.3 Complete De nition of beginning-of-buffer


The basi stru ture of the beginning-of-buffer fun tion has already
been dis ussed. (See Se tion 4.2, \A Simpli ed beginning-of-buffer Def-
inition", page 52.) This se tion des ribes the omplex part of the de nition.
As previously des ribed, when invoked without an argument, beginning-
of-buffer moves the ursor to the beginning of the bu er, leaving the mark
at the previous position. However, when the ommand is invoked with a
number between one and ten, the fun tion onsiders that number to be a
fra tion of the length of the bu er, measured in tenths, and Ema s moves
the ursor that fra tion of the way from the beginning of the bu er. Thus,
you an either all this fun tion with the key ommand M-<, whi h will move
the ursor to the beginning of the bu er, or with a key ommand su h as
C-u 7 M-< whi h will move the ursor to a point 70% of the way through the
bu er. If a number bigger than ten is used for the argument, it moves to
the end of the bu er.
The beginning-of-buffer fun tion an be alled with or without an
argument. The use of the argument is optional.
70 Chapter 5: A Few More Complex Fun tions

5.3.1 Optional Arguments


Unless told otherwise, Lisp expe ts that a fun tion with an argument in
its fun tion de nition will be alled with a value for that argument. If that
does not happen, you get an error and a message that says `Wrong number
of arguments'.
However, optional arguments are a feature of Lisp: a keyword may be
used to tell the Lisp interpreter that an argument is optional. The keyword
is &optional. (The `&' in front of `optional' is part of the keyword.) In a
fun tion de nition, if an argument follows the keyword &optional, a value
does not need to be passed to that argument when the fun tion is alled.
The rst line of the fun tion de nition of beginning-of-buffer therefore
looks like this:
(defun beginning-of-buffer (&optional arg)

In outline, the whole fun tion looks like this:


(defun beginning-of-buffer (&optional arg)
"do umentation..."
(intera tive "P")
(push-mark)
(goto- har
(if-there-is-an-argument
gure-out-where-to-go
else-go-to
(point-min))))

The fun tion is similar to the simplified-beginning-of-buffer fun -


tion ex ept that the intera tive expression has "P" as an argument and
the goto- har fun tion is followed by an if-then-else expression that gures
out where to put the ursor if there is an argument.
The "P" in the intera tive expression tells Ema s to pass a pre x
argument, if there is one, to the fun tion. A pre x argument is made by
typing the hMETAi key followed by a number, or by typing C-u and then a
number (if you don't type a number, C-u defaults to 4).
The true-or-false-test of the if expression is simple: it is simply the
argument arg. If arg has a value that is not nil, whi h will be the ase if
beginning-of-buffer is alled with an argument, then this true-or-false-
test will return true and the then-part of the if expression will be evaluated.
On the other hand, if beginning-of-buffer is not alled with an argument,
the value of arg will be nil and the else-part of the if expression will be
evaluated. The else-part is simply point-min, and when this is the out ome,
the whole goto- har expression is (goto- har (point-min)), whi h is how
we saw the beginning-of-buffer fun tion in its simpli ed form.
What happens in a large bu er 71

5.3.2 beginning-of-buffer with an Argument


When beginning-of-buffer is alled with an argument, an expression is
evaluated whi h al ulates what value to pass to goto- har. This expression
is rather ompli ated at rst sight. It in ludes an inner if expression and
mu h arithmeti . It looks like this:
(if (> (buffer-size) 10000)
;; Avoid over ow for large bu er sizes!
(* (prefix-numeri -value arg) (/ (buffer-size) 10))
(/
(+ 10
(*
(buffer-size) (prefix-numeri -value arg))) 10))
Like other omplex-looking expressions, the onditional expression within
beginning-of-buffer an be disentangled by looking at it as parts of a
template, in this ase, the template for an if-then-else expression. In skeletal
form, the expression looks like this:
(if (bu er-is-large
divide-bu er-size-by-10-and-multiply-by-arg
else-use-alternate- al ulation
The true-or-false-test of this inner if expression he ks the size of the
bu er. The reason for this is that the old Version 18 Ema s used numbers
that are no bigger than eight million or so and in the omputation that
followed, the programmer feared that Ema s might try to use over-large
numbers if the bu er were large. The term `over ow', mentioned in the
omment, means numbers that are over large. Version 21 Ema s uses larger
numbers, but this ode has not been tou hed, if only be ause people now
look at bu ers that are far, far larger than ever before.
There are two ases: if the bu er is large and if it is not.

What happens in a large bu er


In beginning-of-buffer, the inner if expression tests whether the size
of the bu er is greater than 10,000 hara ters. To do this, it uses the >
fun tion and the buffer-size fun tion.
The line looks like this:
(if (> (buffer-size) 10000)
When the bu er is large, the then-part of the if expression is evaluated. It
reads like this (after formatting for easy reading):
(*
(prefix-numeri -value arg)
(/ (buffer-size) 10))
This expression is a multipli ation, with two arguments to the fun tion *.
72 Chapter 5: A Few More Complex Fun tions

The rst argument is (prefix-numeri -value arg). When "P" is used


as the argument for intera tive, the value passed to the fun tion as its
argument is passed a \raw pre x argument", and not a number. (It is a
number in a list.) To perform the arithmeti , a onversion is ne essary, and
prefix-numeri -value does the job.
The se ond argument is (/ (buffer-size) 10). This expression divides
the numeri value of the bu er by ten. This produ es a number that tells
how many hara ters make up one tenth of the bu er size. (In Lisp, / is
used for division, just as * is used for multipli ation.)
In the multipli ation expression as a whole, this amount is multiplied by
the value of the pre x argument|the multipli ation looks like this:
(* numeri -value-of-pre x-arg
number-of- hara ters-in-one-tenth-of-the-bu er )
If, for example, the pre x argument is `7', the one-tenth value will be mul-
tiplied by 7 to give a position 70% of the way through the bu er.
The result of all this is that if the bu er is large, the goto- har expression
reads like this:
(goto- har (* (prefix-numeri -value arg)
(/ (buffer-size) 10)))
This puts the ursor where we want it.

What happens in a small bu er


If the bu er ontains fewer than 10,000 hara ters, a slightly di erent
omputation is performed. You might think this is not ne essary, sin e
the rst omputation ould do the job. However, in a small bu er, the
rst method may not put the ursor on exa tly the desired line; the se ond
method does a better job.
The ode looks like this:
(/ (+ 10 (* (buffer-size) (prefix-numeri -value arg))) 10))
This is ode in whi h you gure out what happens by dis overing how the
fun tions are embedded in parentheses. It is easier to read if you reformat
it with ea h expression indented more deeply than its en losing expression:
(/
(+ 10
(*
(buffer-size)
(prefix-numeri -value arg)))
10))
The Complete beginning-of-buffer 73

Looking at parentheses, we see that the innermost operation is (prefix-


numeri -value arg), whi h onverts the raw argument to a number. This
number is multiplied by the bu er size in the following expression:
(* (buffer-size) (prefix-numeri -value arg)
This multipli ation reates a number that may be larger than the size of
the bu er|seven times larger if the argument is 7, for example. Ten is
then added to this number and nally the large number is divided by ten to
provide a value that is one hara ter larger than the per entage position in
the bu er.
The number that results from all this is passed to goto- har and the
ursor is moved to that point.

5.3.3 The Complete beginning-of-buffer


Here is the omplete text of the beginning-of-buffer fun tion:
(defun beginning-of-buffer (&optional arg)
"Move point to the beginning of the buffer;
leave mark at previous position.
With arg N, put point N/10 of the way
from the true beginning.
Don't use this in Lisp programs!
\(goto- har (point-min)) is faster
and does not set the mark."
(intera tive "P")
(push-mark)
(goto- har
(if arg
(if (> (buffer-size) 10000)
;; Avoid over ow for large bu er sizes!
(* (prefix-numeri -value arg)
(/ (buffer-size) 10))
(/ (+ 10 (* (buffer-size)
(prefix-numeri -value arg)))
10))
(point-min)))
(if arg (forward-line 1)))
Ex ept for two small points, the previous dis ussion shows how this fun tion
works. The rst point deals with a detail in the do umentation string, and
the se ond point on erns the last line of the fun tion.
In the do umentation string, there is referen e to an expression:
\(goto- har (point-min))
A `\' is used before the rst parenthesis of this expression. This `\' tells
the Lisp interpreter that the expression should be printed as shown in the
74 Chapter 5: A Few More Complex Fun tions

do umentation rather than evaluated as a symboli expression, whi h is what


it looks like.
Finally, the last line of the beginning-of-buffer ommand says to move
point to the beginning of the next line if the ommand is invoked with an
argument:
(if arg (forward-line 1)))
This puts the ursor at the beginning of the rst line after the appropriate
tenths position in the bu er. This is a ourish that means that the ursor is
always lo ated at least the requested tenths of the way through the bu er,
whi h is a ni ety that is, perhaps, not ne essary, but whi h, if it did not
o ur, would be sure to draw omplaints.

5.4 Review
Here is a brief summary of some of the topi s overed in this hapter.
or Evaluate ea h argument in sequen e, and return the value of
the rst argument that is not nil; if none return a value that
is not nil, return nil. In brief, return the rst true value of
the arguments; return a true value if one or any of the other are
true.
and Evaluate ea h argument in sequen e, and if any are nil, return
nil; if none are nil, return the value of the last argument. In
brief, return a true value only if all the arguments are true;
return a true value if one and ea h of the others is true.
&optional
A keyword used to indi ate that an argument to a fun tion de -
nition is optional; this means that the fun tion an be evaluated
without the argument, if desired.
prefix-numeri -value
Convert the `raw pre x argument' produ ed by (intera tive
"P") to a numeri value.
forward-line
Move point forward to the beginning of the next line, or if the
argument is greater than one, forward that many lines. If it
an't move as far forward as it is supposed to, forward-line
goes forward as far as it an and then returns a ount of the
number of additional lines it was supposed to move but ouldn't.
erase-buffer
Delete the entire ontents of the urrent bu er.
bufferp Return t if its argument is a bu er; otherwise return nil.
optional Argument Exer ise 75

5.5 optional Argument Exer ise


Write an intera tive fun tion with an optional argument that tests
whether its argument, a number, is greater or less than the value of fill-
olumn, and tells you whi h, in a message. However, if you do not pass an
argument to the fun tion, use 56 as a default value.
76 Chapter 5: A Few More Complex Fun tions
The save-restri tion Spe ial Form 77

6 Narrowing and Widening


Narrowing is a feature of Ema s that makes it possible for you to fo us
on a spe i part of a bu er, and work without a identally hanging other
parts. Narrowing is normally disabled sin e it an onfuse novi es.
With narrowing, the rest of a bu er is made invisible, as if it weren't
there. This is an advantage if, for example, you want to repla e a word in
one part of a bu er but not in another: you narrow to the part you want
and the repla ement is arried out only in that se tion, not in the rest of
the bu er. Sear hes will only work within a narrowed region, not outside of
one, so if you are xing a part of a do ument, you an keep yourself from
a identally nding parts you do not need to x by narrowing just to the
region you want. (The key binding for narrow-to-region is C-x n n.)
However, narrowing does make the rest of the bu er invisible, whi h an
s are people who inadvertently invoke narrowing and think they have deleted
a part of their le. Moreover, the undo ommand (whi h is usually bound
to C-x u) does not turn o narrowing (nor should it), so people an be ome
quite desperate if they do not know that they an return the rest of a bu er
to visibility with the widen ommand. (The key binding for widen is C-x n
w.)
Narrowing is just as useful to the Lisp interpreter as to a human. Often,
an Ema s Lisp fun tion is designed to work on just part of a bu er; or
onversely, an Ema s Lisp fun tion needs to work on all of a bu er that
has been narrowed. The what-line fun tion, for example, removes the
narrowing from a bu er, if it has any narrowing and when it has nished its
job, restores the narrowing to what it was. On the other hand, the ount-
lines fun tion, whi h is alled by what-line, uses narrowing to restri t
itself to just that portion of the bu er in whi h it is interested and then
restores the previous situation.

6.1 The save-restri tion Spe ial Form


In Ema s Lisp, you an use the save-restri tion spe ial form to keep
tra k of whatever narrowing is in e e t, if any. When the Lisp interpreter
meets with save-restri tion, it exe utes the ode in the body of the save-
restri tion expression, and then undoes any hanges to narrowing that the
ode aused. If, for example, the bu er is narrowed and the ode that follows
save-restri tion gets rid of the narrowing, save-restri tion returns the
bu er to its narrowed region afterwards. In the what-line ommand, any
narrowing the bu er may have is undone by the widen ommand that im-
mediately follows the save-restri tion ommand. Any original narrowing
is restored just before the ompletion of the fun tion.
78 Chapter 6: Narrowing and Widening

The template for a save-restri tion expression is simple:


(save-restri tion
body ... )
The body of the save-restri tion is one or more expressions that will be
evaluated in sequen e by the Lisp interpreter.
Finally, a point to note: when you use both save-ex ursion and save-
restri tion, one right after the other, you should use save-ex ursion out-
ermost. If you write them in reverse order, you may fail to re ord narrowing
in the bu er to whi h Ema s swit hes after alling save-ex ursion. Thus,
when written together, save-ex ursion and save-restri tion should be
written like this:
(save-ex ursion
(save-restri tion
body ...))
In other ir umstan es, when not written together, the save-ex ursion
and save-restri tion spe ial forms must be written in the order appro-
priate to the fun tion.
For example,
(save-restri tion
(widen)
(save-ex ursion
body ...))

6.2 what-line
The what-line ommand tells you the number of the line in whi h the
ursor is lo ated. The fun tion illustrates the use of the save-restri tion
and save-ex ursion ommands. Here is the text of the fun tion in full:
(defun what-line ()
"Print the urrent line number (in the buffer) of point."
(intera tive)
(save-restri tion
(widen)
(save-ex ursion
(beginning-of-line)
(message "Line %d"
(1+ ( ount-lines 1 (point)))))))
The fun tion has a do umentation line and is intera tive, as you would
expe t. The next two lines use the fun tions save-restri tion and widen.
The save-restri tion spe ial form notes whatever narrowing is in ef-
fe t, if any, in the urrent bu er and restores that narrowing after the ode
in the body of the save-restri tion has been evaluated.
Exer ise with Narrowing 79

The save-restri tion spe ial form is followed by widen. This fun tion
undoes any narrowing the urrent bu er may have had when what-line
was alled. (The narrowing that was there is the narrowing that save-
restri tion remembers.) This widening makes it possible for the line
ounting ommands to ount from the beginning of the bu er. Otherwise,
they would have been limited to ounting within the a essible region. Any
original narrowing is restored just before the ompletion of the fun tion by
the save-restri tion spe ial form.
The all to widen is followed by save-ex ursion, whi h saves the lo a-
tion of the ursor (i.e., of point) and of the mark, and restores them after
the ode in the body of the save-ex ursion uses the beginning-of-line
fun tion to move point.
(Note that the (widen) expression omes between the save-restri tion
and save-ex ursion spe ial forms. When you write the two save- ...
expressions in sequen e, write save-ex ursion outermost.)
The last two lines of the what-line fun tion are fun tions to ount the
number of lines in the bu er and then print the number in the e ho area.
(message "Line %d"
(1+ ( ount-lines 1 (point)))))))
The message fun tion prints a one-line message at the bottom of the
Ema s s reen. The rst argument is inside of quotation marks and is printed
as a string of hara ters. However, it may ontain `%d', `%s', or `% ' to print
arguments that follow the string. `%d' prints the argument as a de imal, so
the message will say something su h as `Line 243'.
The number that is printed in pla e of the `%d' is omputed by the last
line of the fun tion:
(1+ ( ount-lines 1 (point)))
What this does is ount the lines from the rst position of the bu er, indi-
ated by the 1, up to (point), and then add one to that number. (The 1+
fun tion adds one to its argument.) We add one to it be ause line 2 has only
one line before it, and ount-lines ounts only the lines before the urrent
line.
After ount-lines has done its job, and the message has been printed in
the e ho area, the save-ex ursion restores point and mark to their original
positions; and save-restri tion restores the original narrowing, if any.

6.3 Exer ise with Narrowing


Write a fun tion that will display the rst 60 hara ters of the urrent
bu er, even if you have narrowed the bu er to its latter half so that the rst
line is ina essible. Restore point, mark, and narrowing. For this exer ise,
you need to use save-restri tion, widen, goto- har, point-min, buffer-
substring, message, and other fun tions, a whole potpourri.
80 Chapter 6: Narrowing and Widening
ar and dr 81

7 ar, dr, ons: Fundamental Fun tions

In Lisp, ar, dr, and ons are fundamental fun tions. The ons fun tion
is used to onstru t lists, and the ar and dr fun tions are used to take
them apart.
In the walk through of the opy-region-as-kill fun tion, we will see
ons as well as two variants on dr, namely, set dr and nth dr. (See
Se tion 8.5, \ opy-region-as-kill", page 102.)
The name of the ons fun tion is not unreasonable: it is an abbreviation
of the word ` onstru t'. The origins of the names for ar and dr, on the
other hand, are esoteri : ar is an a ronym from the phrase `Contents of
the Address part of the Register'; and dr (pronoun ed ` ould-er') is an
a ronym from the phrase `Contents of the De rement part of the Register'.
These phrases refer to spe i pie es of hardware on the very early omputer
on whi h the original Lisp was developed. Besides being obsolete, the phrases
have been ompletely irrelevant for more than 25 years to anyone thinking
about Lisp. Nonetheless, although a few brave s holars have begun to use
more reasonable names for these fun tions, the old terms are still in use. In
parti ular, sin e the terms are used in the Ema s Lisp sour e ode, we will
use them in this introdu tion.

7.1 ar and dr
The ar of a list is, quite simply, the rst item in the list. Thus the ar
of the list (rose violet daisy butter up) is rose.
If you are reading this in Info in GNU Ema s, you an see this by evalu-
ating the following:
( ar '(rose violet daisy butter up))
After evaluating the expression, rose will appear in the e ho area.
Clearly, a more reasonable name for the ar fun tion would be first
and this is often suggested.
ar does not remove the rst item from the list; it only reports what it
is. After ar has been applied to a list, the list is still the same as it was. In
the jargon, ar is `non-destru tive'. This feature turns out to be important.
The dr of a list is the rest of the list, that is, the dr fun tion returns
the part of the list that follows the rst item. Thus, while the ar of the
list '(rose violet daisy butter up) is rose, the rest of the list, the value
returned by the dr fun tion, is (violet daisy butter up).
82 Chapter 7: ar, dr, ons: Fundamental Fun tions

You an see this by evaluating the following in the usual way:


( dr '(rose violet daisy butter up))
When you evaluate this, (violet daisy butter up) will appear in the e ho
area.
Like ar, dr does not remove any elements from the list|it just returns
a report of what the se ond and subsequent elements are.
In identally, in the example, the list of owers is quoted. If it were not, the
Lisp interpreter would try to evaluate the list by alling rose as a fun tion.
In this example, we do not want to do that.
Clearly, a more reasonable name for dr would be rest.
(There is a lesson here: when you name new fun tions, onsider very
arefully what you are doing, sin e you may be stu k with the names for far
longer than you expe t. The reason this do ument perpetuates these names
is that the Ema s Lisp sour e ode uses them, and if I did not use them,
you would have a hard time reading the ode; but do, please, try to avoid
using these terms yourself. The people who ome after you will be grateful
to you.)
When ar and dr are applied to a list made up of symbols, su h as the
list (pine fir oak maple), the element of the list returned by the fun tion
ar is the symbol pine without any parentheses around it. pine is the rst
element in the list. However, the dr of the list is a list itself, (fir oak
maple), as you an see by evaluating the following expressions in the usual
way:
( ar '(pine fir oak maple))

( dr '(pine fir oak maple))


On the other hand, in a list of lists, the rst element is itself a list. ar
returns this rst element as a list. For example, the following list ontains
three sub-lists, a list of arnivores, a list of herbivores and a list of sea
mammals:
( ar '((lion tiger heetah)
(gazelle antelope zebra)
(whale dolphin seal)))
In this example, the rst element or ar of the list is the list of arnivores,
(lion tiger heetah), and the rest of the list is ((gazelle antelope
zebra) (whale dolphin seal)).
( dr '((lion tiger heetah)
(gazelle antelope zebra)
(whale dolphin seal)))
It is worth saying again that ar and dr are non-destru tive|that is,
they do not modify or hange lists to whi h they are applied. This is very
important for how they are used.
ons 83

Also, in the rst hapter, in the dis ussion about atoms, I said that in
Lisp, \ ertain kinds of atom, su h as an array, an be separated into parts;
but the me hanism for doing this is di erent from the me hanism for splitting
a list. As far as Lisp is on erned, the atoms of a list are unsplittable."
(See Se tion 1.1.1, \Lisp Atoms", page 1.) The ar and dr fun tions are
used for splitting lists and are onsidered fundamental to Lisp. Sin e they
annot split or gain a ess to the parts of an array, an array is onsidered an
atom. Conversely, the other fundamental fun tion, ons, an put together
or onstru t a list, but not an array. (Arrays are handled by array-spe i
fun tions. See se tion \Arrays" in The GNU Ema s Lisp Referen e Manual.)

7.2 ons
The ons fun tion onstru ts lists; it is the inverse of ar and dr. For
example, ons an be used to make a four element list from the three element
list, (fir oak maple):
( ons 'pine '(fir oak maple))
After evaluating this list, you will see
(pine fir oak maple)
appear in the e ho area. ons puts a new element at the beginning of a list;
it atta hes or pushes elements onto the list.
ons must have a list to atta h to.1 You annot start from absolutely
nothing. If you are building a list, you need to provide at least an empty
list at the beginning. Here is a series of ons expressions that build up a list
of owers. If you are reading this in Info in GNU Ema s, you an evaluate
ea h of the expressions in the usual way; the value is printed in this text
after `)', whi h you may read as `evaluates to'.
( ons 'butter up ())
) (butter up)
( ons 'daisy '(butter up))
) (daisy butter up)
( ons 'violet '(daisy butter up))
) (violet daisy butter up)
( ons 'rose '(violet daisy butter up))
) (rose violet daisy butter up)
In the rst example, the empty list is shown as () and a list made up
of butter up followed by the empty list is onstru ted. As you an see,
the empty list is not shown in the list that was onstru ted. All that you
see is (butter up). The empty list is not ounted as an element of a list
1 A tually, you an ons an element to an atom to produ e a dotted pair. Dotted pairs
are not dis ussed here; see se tion \Dotted Pair Notation" in The GNU Ema s Lisp
Referen e Manual.
84 Chapter 7: ar, dr, ons: Fundamental Fun tions

be ause there is nothing in an empty list. Generally speaking, an empty list


is invisible.
The se ond example, ( ons 'daisy '(butter up)) onstru ts a new,
two element list by putting daisy in front of butter up; and the third
example onstru ts a three element list by putting violet in front of daisy
and butter up.

7.2.1 Find the Length of a List: length


You an nd out how many elements there are in a list by using the Lisp
fun tion length, as in the following examples:
(length '(butter up))
) 1
(length '(daisy butter up))
) 2
(length ( ons 'violet '(daisy butter up)))
) 3
In the third example, the ons fun tion is used to onstru t a three element
list whi h is then passed to the length fun tion as its argument.
We an also use length to ount the number of elements in an empty
list:
(length ())
) 0
As you would expe t, the number of elements in an empty list is zero.
An interesting experiment is to nd out what happens if you try to nd
the length of no list at all; that is, if you try to all length without giving
it an argument, not even an empty list:
(length )
What you see, if you evaluate this, is the error message
Wrong number of arguments: #<subr length>, 0
This means that the fun tion re eives the wrong number of arguments, zero,
when it expe ts some other number of arguments. In this ase, one argument
is expe ted, the argument being a list whose length the fun tion is measuring.
(Note that one list is one argument, even if the list has many elements inside
it.)
The part of the error message that says `#<subr length>' is the name of
the fun tion. This is written with a spe ial notation, `#<subr', that indi ates
that the fun tion length is one of the primitive fun tions written in C rather
than in Ema s Lisp. (`subr' is an abbreviation for `subroutine'.) See se tion
\What Is a Fun tion?" in The GNU Ema s Lisp Referen e Manual, for more
about subroutines.
nth dr 85

7.3 nth dr
The nth dr fun tion is asso iated with the dr fun tion. What it does
is take the dr of a list repeatedly.
If you take the dr of the list (pine fir oak maple), you will be returned
the list (fir oak maple). If you repeat this on what was returned, you
will be returned the list (oak maple). (Of ourse, repeated dring on the
original list will just give you the original dr sin e the fun tion does not
hange the list. You need to evaluate the dr of the dr and so on.) If you
ontinue this, eventually you will be returned an empty list, whi h in this
ase, instead of being shown as () is shown as nil.
For review, here is a series of repeated drs, the text following the `)'
shows what is returned.
( dr '(pine fir oak maple))
)(fir oak maple)
( dr '(fir oak maple))
) (oak maple)
( dr '(oak maple))
)(maple)
( dr '(maple))
) nil
( dr 'nil)
) nil
( dr ())
) nil
You an also do several drs without printing the values in between, like
this:
( dr ( dr '(pine fir oak maple)))
) (oak maple)
In this example, the Lisp interpreter evaluates the innermost list rst. The
innermost list is quoted, so it just passes the list as it is to the innermost dr.
This dr passes a list made up of the se ond and subsequent elements of the
list to the outermost dr, whi h produ es a list omposed of the third and
subsequent elements of the original list. In this example, the dr fun tion is
repeated and returns a list that onsists of the original list without its rst
two elements.
The nth dr fun tion does the same as repeating the all to dr. In the
following example, the argument 2 is passed to the fun tion nth dr, along
with the list, and the value returned is the list without its rst two items,
whi h is exa tly the same as repeating dr twi e on the list:
(nth dr 2 '(pine fir oak maple))
) (oak maple)
86 Chapter 7: ar, dr, ons: Fundamental Fun tions

Using the original four element list, we an see what happens when various
numeri arguments are passed to nth dr, in luding 0, 1, and 5:
;; Leave the list as it was.
(nth dr 0 '(pine fir oak maple))
) (pine fir oak maple)
;; Return a opy without the rst element.
(nth dr 1 '(pine fir oak maple))
) (fir oak maple)
;; Return a opy of the list without three elements.
(nth dr 3 '(pine fir oak maple))
) (maple)
;; Return a opy la king all four elements.
(nth dr 4 '(pine fir oak maple))
) nil
;; Return a opy la king all elements.
(nth dr 5 '(pine fir oak maple))
) nil

7.4 nth
The nth dr fun tion takes the dr of a list repeatedly. The nth fun tion
takes the ar of the result returned by nth dr. It returns the Nth element
of the list.
Thus, if it were not de ned in C for speed, the de nition of nth would
be:
(defun nth (n list)
"Returns the Nth element of LIST.
N ounts from zero. If LIST is not that long, nil is returned."
( ar (nth dr n list)))

(Originally, nth was de ned in Ema s Lisp in `subr.el', but its de nition
was redone in C in the 1980s.)
The nth fun tion returns a single element of a list. This an be very
onvenient.
Note that the elements are numbered from zero, not one. That is to
say, the rst element of a list, its ar is the zeroth element. This is alled
`zero-based' ounting and often bothers people who are a ustomed to the
rst element in a list being number one, whi h is `one-based'.
set dr 87

For example:
(nth 0 '("one" "two" "three"))
) "one"

(nth 1 '("one" "two" "three"))


) "two"
It is worth mentioning that nth, like nth dr and dr, does not hange
the original list|the fun tion is non-destru tive. This is in sharp ontrast
to the set ar and set dr fun tions.

7.5 set ar
As you might guess from their names, the set ar and set dr fun tions
set the ar or the dr of a list to a new value. They a tually hange the
original list, unlike ar and dr whi h leave the original list as it was. One
way to nd out how this works is to experiment. We will start with the
set ar fun tion.
First, we an make a list and then set the value of a variable to the list,
using the setq fun tion. Here is a list of animals:
(setq animals '(antelope giraffe lion tiger))
If you are reading this in Info inside of GNU Ema s, you an evaluate this
expression in the usual fashion, by positioning the ursor after the expression
and typing C-x C-e. (I'm doing this right here as I write this. This is
one of the advantages of having the interpreter built into the omputing
environment.)
When we evaluate the variable animals, we see that it is bound to the
list (antelope giraffe lion tiger):
animals
) (antelope giraffe lion tiger)
Put another way, the variable animals points to the list (antelope giraffe
lion tiger).
Next, evaluate the fun tion set ar while passing it two arguments, the
variable animals and the quoted symbol hippopotamus; this is done by
writing the three element list (set ar animals 'hippopotamus) and then
evaluating it in the usual fashion:
(set ar animals 'hippopotamus)
After evaluating this expression, evaluate the variable animals again. You
will see that the list of animals has hanged:
animals
) (hippopotamus giraffe lion tiger)
The rst element on the list, antelope is repla ed by hippopotamus.
88 Chapter 7: ar, dr, ons: Fundamental Fun tions

So we an see that set ar did not add a new element to the list as ons
would have; it repla ed giraffe with hippopotamus; it hanged the list.

7.6 set dr
The set dr fun tion is similar to the set ar fun tion, ex ept that the
fun tion repla es the se ond and subsequent elements of a list rather than
the rst element.
To see how this works, set the value of the variable to a list of domesti-
ated animals by evaluating the following expression:
(setq domesti ated-animals '(horse ow sheep goat))
If you now evaluate the list, you will be returned the list (horse ow sheep
goat):
domesti ated-animals
) (horse ow sheep goat)
Next, evaluate set dr with two arguments, the name of the variable
whi h has a list as its value, and the list to whi h the dr of the rst list
will be set;
(set dr domesti ated-animals '( at dog))
If you evaluate this expression, the list ( at dog) will appear in the e ho
area. This is the value returned by the fun tion. The result we are inter-
ested in is the \side e e t", whi h we an see by evaluating the variable
domesti ated-animals:
domesti ated-animals
) (horse at dog)
Indeed, the list is hanged from (horse ow sheep goat) to (horse at
dog). The dr of the list is hanged from ( ow sheep goat) to ( at dog).

7.7 Exer ise


Constru t a list of four birds by evaluating several expressions with ons.
Find out what happens when you ons a list onto itself. Repla e the rst
element of the list of four birds with a sh. Repla e the rest of that list with
a list of other sh.
zap-to- har 89

8 Cutting and Storing Text


Whenever you ut or lip text out of a bu er with a `kill' ommand in
GNU Ema s, it is stored in a list and you an bring it ba k with a `yank'
ommand.
(The use of the word `kill' in Ema s for pro esses whi h spe i ally do
not destroy the values of the entities is an unfortunate histori al a ident.
A mu h more appropriate word would be ` lip' sin e that is what the kill
ommands do; they lip text out of a bu er and put it into storage from
whi h it an be brought ba k. I have often been tempted to repla e globally
all o urren es of `kill' in the Ema s sour es with ` lip' and all o urren es
of `killed' with ` lipped'.)
When text is ut out of a bu er, it is stored on a list. Su essive pie es
of text are stored on the list su essively, so the list might look like this:
("a pie e of text" "previous pie e")
The fun tion ons an be used to add a pie e of text to the list, like this:
( ons "another pie e"
'("a pie e of text" "previous pie e"))
If you evaluate this expression, a list of three elements will appear in the
e ho area:
("another pie e" "a pie e of text" "previous pie e")
With the ar and nth dr fun tions, you an retrieve whi hever pie e of
text you want. For example, in the following ode, nth dr 1 ... returns
the list with the rst item removed; and the ar returns the rst element of
that remainder|the se ond element of the original list:
( ar (nth dr 1 '("another pie e"
"a pie e of text"
"previous pie e")))
) "a pie e of text"
The a tual fun tions in Ema s are more omplex than this, of ourse.
The ode for utting and retrieving text has to be written so that Ema s
an gure out whi h element in the list you want|the rst, se ond, third,
or whatever. In addition, when you get to the end of the list, Ema s should
give you the rst element of the list, rather than nothing at all.
The list that holds the pie es of text is alled the kill ring. This hapter
leads up to a des ription of the kill ring and how it is used by rst tra ing how
the zap-to- har fun tion works. This fun tion uses (or ` alls') a fun tion
that invokes a fun tion that manipulates the kill ring. Thus, before rea hing
the mountains, we limb the foothills.
A subsequent hapter des ribes how text that is ut from the bu er is
retrieved. See Chapter 10, \Yanking Text Ba k", page 117.
90 Chapter 8: Cutting and Storing Text

8.1 zap-to- har


The zap-to- har fun tion barely hanged between GNU Ema s version
19 and GNU Ema s version 21. However, zap-to- har alls another fun -
tion, kill-region, whi h enjoyed a major rewrite on the way to version
21.
The kill-region fun tion in Ema s 19 is omplex, but does not use ode
that is important at this time. We will skip it.
The kill-region fun tion in Ema s 21 is easier to read than the same
fun tion in Ema s 19 and introdu es a very important on ept, that of error
handling. We will walk through the fun tion.
But rst, let us look at the intera tive zap-to- har fun tion.
The GNU Ema s version 19 and version 21 implementations of the zap-
to- har fun tion are nearly identi al in form, and they work alike. The
fun tion removes the text in the region between the lo ation of the ursor
(i.e., of point) up to and in luding the next o urren e of a spe i ed hara -
ter. The text that zap-to- har removes is put in the kill ring; and it an be
retrieved from the kill ring by typing C-y (yank). If the ommand is given
an argument, it removes text through that number of o urren es. Thus, if
the ursor were at the beginning of this senten e and the hara ter were `s',
`Thus' would be removed. If the argument were two, `Thus, if the urs'
would be removed, up to and in luding the `s' in ` ursor'.
If the spe i ed hara ter is not found, zap-to- har will say \Sear h
failed", tell you the hara ter you typed, and not remove any text.
In order to determine how mu h text to remove, zap-to- har uses a
sear h fun tion. Sear hes are used extensively in ode that manipulates text,
and we will fo us attention on them as well as on the deletion ommand.
Here is the omplete text of the version 19 implementation of the fun tion:
(defun zap-to- har (arg har) ; version 19 implementation
"Kill up to and in luding ARG'th o urren e of CHAR.
Goes ba kward if ARG is negative; error if CHAR not found."
(intera tive "*p\n Zap to har: ")
(kill-region (point)
(progn
(sear h-forward
( har-to-string har) nil nil arg)
(point))))

8.1.1 The intera tive Expression


The intera tive expression in the zap-to- har ommand looks like this:
(intera tive "*p\n Zap to har: ")
The part within quotation marks, "*p\n Zap to har: ", spe i es three
di erent things. First, and most simply, the asterisk, `*', auses an error to
The sear h-forward Fun tion 91

be signalled if the bu er is read-only. This means that if you try zap-to-


har in a read-only bu er you will not be able to remove text, and you will
re eive a message that says \Bu er is read-only"; your terminal may beep
at you as well.
The version 21 implementation does not have the asterisk, `*'. The fun -
tion works the same as in version 19: in both ases, it annot remove text
from a read-only bu er but the fun tion does opy the text that would have
been removed to the kill ring. Also, in both ases, you see an error message.
However, the version 19 implementation opies text from a read-only
bu er only be ause of a mistake in the implementation of intera tive.
A ording to the do umentation for intera tive, the asterisk, `*', should
prevent the zap-to- har fun tion from doing anything at all when the bu er
is read only. The fun tion should not opy the text to the kill ring. It is a
bug that it does.
In version 21, intera tive is implemented orre tly. So the asterisk, `*',
had to be removed from the intera tive spe i ation. If you insert an `*' and
evaluate the fun tion de nition, then the next time you run the zap-to- har
fun tion on a read-only bu er, you will not opy any text.
That hange aside, and a hange to the do umentation, the two versions
of the zap-to- har fun tion are identi al.
Let us ontinue with the intera tive spe i ation.
The se ond part of "*p\n Zap to har: " is the `p'. This part is sepa-
rated from the next part by a newline, `\n'. The `p' means that the rst
argument to the fun tion will be passed the value of a `pro essed pre x'.
The pre x argument is passed by typing C-u and a number, or M- and a
number. If the fun tion is alled intera tively without a pre x, 1 is passed
to this argument.
The third part of "*p\n Zap to har: " is ` Zap to har: '. In this part,
the lower ase ` ' indi ates that intera tive expe ts a prompt and that the
argument will be a hara ter. The prompt follows the ` ' and is the string
`Zap to har: ' (with a spa e after the olon to make it look good).
What all this does is prepare the arguments to zap-to- har so they are
of the right type, and give the user a prompt.

8.1.2 The Body of zap-to- har


The body of the zap-to- har fun tion ontains the ode that kills (that
is, removes) the text in the region from the urrent position of the ursor
up to and in luding the spe i ed hara ter. The rst part of the ode looks
like this:
(kill-region (point) ...
(point) is the urrent position of the ursor.
The next part of the ode is an expression using progn. The body of the
progn onsists of alls to sear h-forward and point.
92 Chapter 8: Cutting and Storing Text

It is easier to understand how progn works after learning about sear h-


forward, so we will look at sear h-forward and then at progn.

8.1.3 The sear h-forward Fun tion


The sear h-forward fun tion is used to lo ate the zapped-for- hara ter
in zap-to- har. If the sear h is su essful, sear h-forward leaves point
immediately after the last hara ter in the target string. (In zap-to- har,
the target string is just one hara ter long.) If the sear h is ba kwards,
sear h-forward leaves point just before the rst hara ter in the target.
Also, sear h-forward returns t for true. (Moving point is therefore a `side
e e t'.)
In zap-to- har, the sear h-forward fun tion looks like this:
(sear h-forward ( har-to-string har) nil nil arg)
The sear h-forward fun tion takes four arguments:
1. The rst argument is the target, what is sear hed for. This must be a
string, su h as `"z"'.
As it happens, the argument passed to zap-to- har is a single hara -
ter. Be ause of the way omputers are built, the Lisp interpreter may
treat a single hara ter as being di erent from a string of hara ters.
Inside the omputer, a single hara ter has a di erent ele troni format
than a string of one hara ter. (A single hara ter an often be re orded
in the omputer using exa tly one byte; but a string may be longer, and
the omputer needs to be ready for this.) Sin e the sear h-forward
fun tion sear hes for a string, the hara ter that the zap-to- har fun -
tion re eives as its argument must be onverted inside the omputer
from one format to the other; otherwise the sear h-forward fun tion
will fail. The har-to-string fun tion is used to make this onversion.
2. The se ond argument bounds the sear h; it is spe i ed as a position in
the bu er. In this ase, the sear h an go to the end of the bu er, so
no bound is set and the se ond argument is nil.
3. The third argument tells the fun tion what it should do if the sear h
fails|it an signal an error (and print a message) or it an return nil.
A nil as the third argument auses the fun tion to signal an error when
the sear h fails.
4. The fourth argument to sear h-forward is the repeat ount|how
many o urren es of the string to look for. This argument is optional
and if the fun tion is alled without a repeat ount, this argument is
passed the value 1. If this argument is negative, the sear h goes ba k-
wards.
Summing up zap-to- har 93

In template form, a sear h-forward expression looks like this:


(sear h-forward "target-string "
limit-of-sear h
what-to-do-if-sear h-fails
repeat- ount)
We will look at progn next.

8.1.4 The progn Spe ial Form


progn is a spe ial form that auses ea h of its arguments to be evaluated
in sequen e and then returns the value of the last one. The pre eding ex-
pressions are evaluated only for the side e e ts they perform. The values
produ ed by them are dis arded.
The template for a progn expression is very simple:
(progn
body ...)
In zap-to- har, the progn expression has to do two things: put point
in exa tly the right position; and return the lo ation of point so that kill-
region will know how far to kill to.
The rst argument to the progn is sear h-forward. When sear h-
forward nds the string, the fun tion leaves point immediately after the
last hara ter in the target string. (In this ase the target string is just one
hara ter long.) If the sear h is ba kwards, sear h-forward leaves point
just before the rst hara ter in the target. The movement of point is a side
e e t.
The se ond and last argument to progn is the expression (point). This
expression returns the value of point, whi h in this ase will be the lo ation
to whi h it has been moved by sear h-forward. This value is returned
by the progn expression and is passed to kill-region as kill-region's
se ond argument.

8.1.5 Summing up zap-to- har


Now that we have seen how sear h-forward and progn work, we an
see how the zap-to- har fun tion works as a whole.
The rst argument to kill-region is the position of the ursor when the
zap-to- har ommand is given|the value of point at that time. Within
the progn, the sear h fun tion then moves point to just after the zapped-
to- hara ter and point returns the value of this lo ation. The kill-region
fun tion puts together these two values of point, the rst one as the beginning
of the region and the se ond one as the end of the region, and removes the
region.
The progn spe ial form is ne essary be ause the kill-region ommand
takes two arguments; and it would fail if sear h-forward and point ex-
94 Chapter 8: Cutting and Storing Text

pressions were written in sequen e as two additional arguments. The progn


expression is a single argument to kill-region and returns the one value
that kill-region needs for its se ond argument.

8.2 kill-region

The zap-to- har fun tion uses the kill-region fun tion. This fun tion
lips text from a region and opies that text to the kill ring, from whi h it
may be retrieved.
The Ema s 21 version of that fun tion uses ondition- ase and opy-
region-as-kill, both of whi h we will explain. ondition- ase is an
important spe ial form.
In essen e, the kill-region fun tion alls ondition- ase, whi h takes
three arguments. In this fun tion, the rst argument does nothing. The
se ond argument ontains the ode that does the work when all goes well.
The third argument ontains the ode that is alled in the event of an error.
We will go through the ondition- ase ode in a moment. First, let us
look at the omplete de nition of kill-region, with omments added:
(defun kill-region (beg end)
"Kill between point and mark.
The text is deleted but saved in the kill ring."
(intera tive "r")
;; 1. ` ondition- ase' takes three arguments.
;; If the first argument is nil, as it is here,
;; information about the error signal is not
;; stored for use by another fun tion.
( ondition- ase nil
;; 2. The se ond argument to ` ondition- ase'
;; tells the Lisp interpreter what to do when all goes well.
;; The `delete-and-extra t-region' fun tion usually does the
;; work. If the beginning and ending of the region are both
;; the same, then the variable `string' will be empty, or nil
(let ((string (delete-and-extra t-region beg end)))
;; `when' is an `if' lause that annot take an `else-part'.
;; Ema s normally sets the value of `last- ommand' to the
;; previous ommand.
ondition- ase 95

;; `kill-append' on atenates the new string and the old.


;; `kill-new' inserts text into a new item in the kill ring.
(when string
(if (eq last- ommand 'kill-region)
;; if true, prepend string
(kill-append string (< end beg))
(kill-new string)))
(setq this- ommand 'kill-region))
;; 3. The third argument to ` ondition- ase' tells the interpreter
;; what to do with an error.
;; The third argument has a onditions part and a body part.
;; If the onditions are met (in this ase,
;; if text or buffer is read-only)
;; then the body is exe uted.
((buffer-read-only text-read-only) ;; this is the if-part
;; then...
( opy-region-as-kill beg end)
(if kill-read-only-ok ;; usually this variable is nil
(message "Read only text opied to kill ring")
;; or else, signal an error if the buffer is read-only;
(barf-if-buffer-read-only)
;; and, in any ase, signal that the text is read-only.
(signal 'text-read-only (list ( urrent-buffer)))))))

8.2.1 ondition- ase


As we have seen earlier (see Se tion 1.3, \Generate an Error Message",
page 4), when the Ema s Lisp interpreter has trouble evaluating an expres-
sion, it provides you with help; in the jargon, this is alled \signaling an
error". Usually, the omputer stops the program and shows you a message.
However, some programs undertake ompli ated a tions. They should not
simply stop on an error. In the kill-region fun tion, the most likely error
is that you will try to kill text that is read-only and annot be removed. So
the kill-region fun tion ontains ode to handle this ir umstan e. This
ode, whi h makes up the body of the kill-region fun tion, is inside of a
ondition- ase spe ial form.
The template for ondition- ase looks like this:
( ondition- ase
var
bodyform
error-handler ...)
The se ond argument, bodyform, is straightforward. The ondition-
ase spe ial form auses the Lisp interpreter to evaluate the ode in body-
96 Chapter 8: Cutting and Storing Text

form. If no error o urs, the spe ial form returns the ode's value and
produ es the side-e e ts, if any.
In short, the bodyform part of a ondition- ase expression determines
what should happen when everything works orre tly.
However, if an error o urs, among its other a tions, the fun tion gener-
ating the error signal will de ne one or more error ondition names.
An error handler is the third argument to ondition ase. An error
handler has two parts, a ondition-name and a body. If the ondition-name
part of an error handler mat hes a ondition name generated by an error,
then the body part of the error handler is run.
As you will expe t, the ondition-name part of an error handler may be
either a single ondition name or a list of ondition names.
Also, a omplete ondition- ase expression may ontain more than one
error handler. When an error o urs, the rst appli able handler is run.
Lastly, the rst argument to the ondition- ase expression, the var
argument, is sometimes bound to a variable that ontains information about
the error. However, if that argument is nil, as is the ase in kill-region,
that information is dis arded.
In brief, in the kill-region fun tion, the ode ondition- ase works
like this:
If no errors, run only this ode
but, if errors, run this other ode.

8.2.2 delete-and-extra t-region


A ondition- ase expression has two parts, a part that is evaluated in
the expe tation that all will go well, but whi h may generate an error; and
a part that is evaluated when there is an error.
First, let us look at the ode in kill-region that is run in the expe tation
that all goes well. This is the ore of the fun tion. The ode looks like this:
(let ((string (delete-and-extra t-region beg end)))
(when string
(if (eq last- ommand 'kill-region)
(kill-append string (< end beg))
(kill-new string)))
(setq this- ommand 'kill-region))
It looks ompli ated be ause we have the new fun tions delete-and-
extra t-region, kill-append, and kill-new as well as the new variables,
last- ommand and this- ommand.
The delete-and-extra t-region fun tion is straightforward. It is a
built-in fun tion that deletes the text in a region (a side e e t) and also
returns that text. This is the fun tion that a tually removes the text. (And
if it annot do that, it signals the error.)
delete-and-extra t-region: Digressing into C 97

In this let expression, the text that delete-and-extra t-region re-


turns is pla ed in the lo al variable alled `string'. This is the text that is
removed from the bu er. (To be more pre ise, the variable is set to point
to the address of the extra ted text; to say it is `pla ed in' the variable is
simply a shorthand.)
If the variable `string' does point to text, that text is added to the kill
ring. The variable will have a nil value if no text was removed.
The ode uses when to determine whether the variable `string' points
to text. A when statement is simply a programmers' onvenien e. A when
statement is an if statement without the possibility of an else lause. In
your mind, you an repla e when with if and understand what goes on.
That is what the Lisp interpreter does.
Te hni ally speaking, when is a Lisp ma ro. A Lisp ma ro enables you to
de ne new ontrol onstru ts and other language features. It tells the inter-
preter how to ompute another Lisp expression whi h will in turn ompute
the value. In this ase, the `other expression' is an if expression. For more
about Lisp ma ros, see se tion \Ma ros" in The GNU Ema s Lisp Referen e
Manual. The C programming language also provides ma ros. These are
di erent, but also useful. We will brie y look at C ma ros in Se tion 8.3,
\delete-and-extra t-region: Digressing into C", page 98.
If the string has ontent, then another onditional expression is exe uted.
This is an if with both a then-part and an else-part.
(if (eq last- ommand 'kill-region)
(kill-append string (< end beg))
(kill-new string)))
The then-part is evaluated if the previous ommand was another all to
kill-region; if not, the else-part is evaluated.
last- ommand is a variable that omes with Ema s that we have not seen
before. Normally, whenever a fun tion is exe uted, Ema s sets the value of
last- ommand to the previous ommand.
In this segment of the de nition, the if expression he ks whether the
previous ommand was kill-region. If it was,
(kill-append string (< end beg))
on atenates a opy of the newly lipped text to the just previously lipped
text in the kill ring. (If the (< end beg)) expression is true, kill-append
prepends the string to the just previously lipped text. For a detailed dis-
ussion, see \The kill-append fun tion", page 104.)
If you then yank ba k the text, i.e., `paste' it, you get both pie es of
text at on e. That way, if you delete two words in a row, and then yank
them ba k, you get both words, in their proper order, with one yank. (The
(< end beg)) expression makes sure the order is orre t.)
98 Chapter 8: Cutting and Storing Text

On the other hand, if the previous ommand is not kill-region, then


the kill-new fun tion is alled, whi h adds the text to the kill ring as the
latest item, and sets the kill-ring-yank-pointer variable to point to it.

8.3 delete-and-extra t-region: Digressing into C


The zap-to- har ommand uses the delete-and-extra t-region fun -
tion, whi h in turn uses two other fun tions, opy-region-as-kill and
del_range_1. The opy-region-as-kill fun tion will be des ribed in a
following se tion; it puts a opy of the region in the kill ring so it an be
yanked ba k. (See Se tion 8.5, \ opy-region-as-kill", page 102.)
The delete-and-extra t-region fun tion removes the ontents of a
region and you annot get them ba k.
Unlike the other ode dis ussed here, delete-and-extra t-region is
not written in Ema s Lisp; it is written in C and is one of the primitives of
the GNU Ema s system. Sin e it is very simple, I will digress brie y from
Lisp and des ribe it here.
Like many of the other Ema s primitives, delete-and-extra t-region
is written as an instan e of a C ma ro, a ma ro being a template for ode.
The omplete ma ro looks like this:
DEFUN ("delete-and-extra t-region", Fdelete_and_extra t_region,
Sdelete_and_extra t_region, 2, 2, 0,
"Delete the text between START and END and return it.")
(start, end)
Lisp_Obje t start, end;
{
validate_region (&start, &end);
return del_range_1 (XINT (start), XINT (end), 1, 1);
}
Without going into the details of the ma ro writing pro ess, let me point
out that this ma ro starts with the word DEFUN. The word DEFUN was hosen
sin e the ode serves the same purpose as defun does in Lisp. The word
DEFUN is followed by seven parts inside of parentheses:
 The rst part is the name given to the fun tion in Lisp, delete-and-
extra t-region.
 The se ond part is the name of the fun tion in C, Fdelete_and_
extra t_region. By onvention, it starts with `F'. Sin e C does not
use hyphens in names, unders ores are used instead.
 The third part is the name for the C onstant stru ture that re ords
information on this fun tion for internal use. It is the name of the
fun tion in C but begins with an `S' instead of an `F'.
 The fourth and fth parts spe ify the minimum and maximum number
of arguments the fun tion an have. This fun tion demands exa tly 2
arguments.
delete-and-extra t-region: Digressing into C 99

 The sixth part is nearly like the argument that follows the intera tive
de laration in a fun tion written in Lisp: a letter followed, perhaps, by
a prompt. The only di eren e from the Lisp is when the ma ro is alled
with no arguments. Then you write a 0 (whi h is a `null string'), as in
this ma ro.
If you were to spe ify arguments, you would pla e them between quo-
tation marks. The C ma ro for goto- har in ludes "NGoto har: " in
this position to indi ate that the fun tion expe ts a raw pre x, in this
ase, a numeri al lo ation in a bu er, and provides a prompt.
 The seventh part is a do umentation string, just like the one for a fun -
tion written in Ema s Lisp, ex ept that every newline must be written
expli itly as `\n' followed by a ba kslash and arriage return.
Thus, the rst two lines of do umentation for goto- har are written
like this:
"Set point to POSITION, a number or marker.\n\
Beginning of buffer is position (point-min), end is (point-max).

In a C ma ro, the formal parameters ome next, with a statement of


what kind of obje t they are, followed by what might be alled the `body'
of the ma ro. For delete-and-extra t-region the `body' onsists of the
following two lines:
validate_region (&start, &end);
return del_range_1 (XINT (start), XINT (end), 1, 1);
The rst fun tion, validate_region he ks whether the values passed
as the beginning and end of the region are the proper type and are within
range. The se ond fun tion, del_range_1, a tually deletes the text.
del_range_1 is a omplex fun tion we will not look into. It updates the
bu er and does other things.
However, it is worth looking at the two arguments passed to del_range.
These are XINT (start) and XINT (end).
As far as the C language is on erned, start and end are two integers
that mark the beginning and end of the region to be deleted1 .
In early versions of Ema s, these two numbers were thirty-two bits long,
but the ode is slowly being generalized to handle other lengths. Three of
the available bits are used to spe ify the type of information and a fourth
bit is used for handling the omputer's memory; the remaining bits are used
as ` ontent'.
`XINT' is a C ma ro that extra ts the relevant number from the longer
olle tion of bits; the four other bits are dis arded.

1 More pre isely, and requiring more expert knowledge to understand, the two integers
are of type `Lisp Obje t', whi h an also be a C union instead of an integer type.
100 Chapter 8: Cutting and Storing Text

The ommand in delete-and-extra t-region looks like this:


del_range_1 (XINT (start), XINT (end), 1, 1);
It deletes the region between the beginning position, start, and the ending
position, end.
From the point of view of the person writing Lisp, Ema s is all very
simple; but hidden underneath is a great deal of omplexity to make it all
work.

8.4 Initializing a Variable with defvar


Unlike the delete-and-extra t-region fun tion, the opy-region-as-
kill fun tion is written in Ema s Lisp. Two fun tions within it, kill-
append and kill-new, opy a region in a bu er and save it in a variable
alled the kill-ring. This se tion des ribes how the kill-ring variable is
reated and initialized using the defvar spe ial form.
(Again we note that the term kill-ring is a misnomer. The text that
is lipped out of the bu er an be brought ba k; it is not a ring of orpses,
but a ring of resurre table text.)
In Ema s Lisp, a variable su h as the kill-ring is reated and given an
initial value by using the defvar spe ial form. The name omes from \de ne
variable".
The defvar spe ial form is similar to setq in that it sets the value of a
variable. It is unlike setq in two ways: rst, it only sets the value of the
variable if the variable does not already have a value. If the variable already
has a value, defvar does not override the existing value. Se ond, defvar
has a do umentation string.
(Another spe ial form, def ustom, is designed for variables that people
ustomize. It has more features than defvar. (See Se tion 16.2, \Setting
Variables with def ustom", page 214.)
You an see the urrent value of a variable, any variable, by using the
des ribe-variable fun tion, whi h is usually invoked by typing C-h v. If
you type C-h v and then kill-ring (followed by hRETi) when prompted, you
will see what is in your urrent kill ring|this may be quite a lot! Conversely,
if you have been doing nothing this Ema s session ex ept read this do ument,
you may have nothing in it. Also, you will see the do umentation for kill-
ring:
Do umentation:
List of killed text sequen es.
Sin e the kill ring is supposed to intera t ni ely with ut-and-paste
fa ilities offered by window systems, use of this variable should
opy-region-as-kill 101

intera t ni ely with `interprogram- ut-fun tion' and


`interprogram-paste-fun tion'. The fun tions `kill-new',
`kill-append', and ` urrent-kill' are supposed to implement this
intera tion; you may want to use them instead of manipulating the kill
ring dire tly.
The kill ring is de ned by a defvar in the following way:
(defvar kill-ring nil
"List of killed text sequen es.
...")
In this variable de nition, the variable is given an initial value of nil, whi h
makes sense, sin e if you have saved nothing, you want nothing ba k if you
give a yank ommand. The do umentation string is written just like the
do umentation string of a defun. As with the do umentation string of the
defun, the rst line of the do umentation should be a omplete senten e,
sin e some ommands, like apropos, print only the rst line of do umenta-
tion. Su eeding lines should not be indented; otherwise they look odd when
you use C-h v (des ribe-variable).

8.4.1 defvar and an asterisk


In the past, Ema s used the defvar spe ial form both for internal vari-
ables that you would not expe t a user to hange and for variables that you
do expe t a user to hange. Although you an still use defvar for user us-
tomizable variables, please use def ustom instead, sin e that spe ial form
provides a path into the Customization ommands. (See Se tion 16.2, \Set-
ting Variables with def ustom", page 214.)
When you spe i ed a variable using the defvar spe ial form, you ould
distinguish a readily settable variable from others by typing an asterisk, `*',
in the rst olumn of its do umentation string. For example:
(defvar shell- ommand-default-error-buffer nil
"*Buffer name for `shell- ommand' ... error output.
... ")
This means that you ould (and still an) use the edit-options ommand
to hange the value of shell- ommand-default-error-buffer temporarily.
However, options set using edit-options are set only for the duration
of your editing session. The new values are not saved between sessions.
Ea h time Ema s starts, it reads the original value, unless you hange the
value within your `.ema s' le, either by setting it manually or by using
ustomize. See Chapter 16, \Your `.ema s' File", page 213.
For me, the major use of the edit-options ommand is to suggest vari-
ables that I might want to set in my `.ema s' le. I urge you to look through
the list. (See se tion \Editing Variable Values" in The GNU Ema s Manual.)
102 Chapter 8: Cutting and Storing Text

8.5 opy-region-as-kill
The opy-region-as-kill fun tion opies a region of text from a bu er
and (via either kill-append or kill-new) saves it in the kill-ring.
If you all opy-region-as-kill immediately after a kill-region om-
mand, Ema s appends the newly opied text to the previously opied text.
This means that if you yank ba k the text, you get it all, from both this and
the previous operation. On the other hand, if some other ommand pre edes
the opy-region-as-kill, the fun tion opies the text into a separate entry
in the kill ring.
Here is the omplete text of the version 21 opy-region-as-kill fun -
tion:
(defun opy-region-as-kill (beg end)
"Save the region as if killed, but don't kill it.
In Transient Mark mode, dea tivate the mark.
If `interprogram- ut-fun tion' is non-nil, also save
the text for a window system ut and paste."
(intera tive "r")
(if (eq last- ommand 'kill-region)
(kill-append (buffer-substring beg end) (< end beg))
(kill-new (buffer-substring beg end)))
(if transient-mark-mode
(setq dea tivate-mark t))
nil)
As usual, this fun tion an be divided into its omponent parts:
(defun opy-region-as-kill (argument-list)
"do umentation..."
(intera tive "r")
body ...)
The arguments are beg and end and the fun tion is intera tive with "r",
so the two arguments must refer to the beginning and end of the region.
If you have been reading though this do ument from the beginning, under-
standing these parts of a fun tion is almost be oming routine.
The do umentation is somewhat onfusing unless you remember that the
word `kill' has a meaning di erent from its usual meaning. The `Transient
Mark' and interprogram- ut-fun tion omments explain ertain side-
e e ts.
After you on e set a mark, a bu er always ontains a region. If you
wish, you an use Transient Mark mode to highlight the region temporarily.
(No one wants to highlight the region all the time, so Transient Mark mode
highlights it only at appropriate times. Many people turn o Transient Mark
mode, so the region is never highlighted.)
The Body of opy-region-as-kill 103

Also, a windowing system allows you to opy, ut, and paste among di er-
ent programs. In the X windowing system, for example, the interprogram-
ut-fun tion fun tion is x-sele t-text, whi h works with the windowing
system's equivalent of the Ema s kill ring.
The body of the opy-region-as-kill fun tion starts with an if
lause. What this lause does is distinguish between two di erent situa-
tions: whether or not this ommand is exe uted immediately after a previ-
ous kill-region ommand. In the rst ase, the new region is appended
to the previously opied text. Otherwise, it is inserted into the beginning of
the kill ring as a separate pie e of text from the previous pie e.
The last two lines of the fun tion prevent the region from lighting up if
Transient Mark mode is turned on.
The body of opy-region-as-kill merits dis ussion in detail.

8.5.1 The Body of opy-region-as-kill


The opy-region-as-kill fun tion works in mu h the same way as the
kill-region fun tion (see Se tion 8.2, \kill-region", page 94). Both are
written so that two or more kills in a row ombine their text into a single
entry. If you yank ba k the text from the kill ring, you get it all in one pie e.
Moreover, kills that kill forward from the urrent position of the ursor are
added to the end of the previously opied text and ommands that opy text
ba kwards add it to the beginning of the previously opied text. This way,
the words in the text stay in the proper order.
Like kill-region, the opy-region-as-kill fun tion makes use of the
last- ommand variable that keeps tra k of the previous Ema s ommand.
Normally, whenever a fun tion is exe uted, Ema s sets the value of this-
ommand to the fun tion being exe uted (whi h in this ase would be opy-
region-as-kill). At the same time, Ema s sets the value of last- ommand
to the previous value of this- ommand.
In the rst part of the body of the opy-region-as-kill fun tion, an if
expression determines whether the value of last- ommand is kill-region.
If so, the then-part of the if expression is evaluated; it uses the kill-append
fun tion to on atenate the text opied at this all to the fun tion with the
text already in the rst element (the ar) of the kill ring. On the other
hand, if the value of last- ommand is not kill-region, then the opy-
region-as-kill fun tion atta hes a new element to the kill ring using the
kill-new fun tion.
104 Chapter 8: Cutting and Storing Text

The if expression reads as follows; it uses eq, whi h is a fun tion we have
not yet seen:
(if (eq last- ommand 'kill-region)
;; then-part
(kill-append (buffer-substring beg end) (< end beg))
;; else-part
(kill-new (buffer-substring beg end)))
The eq fun tion tests whether its rst argument is the same Lisp obje t as
its se ond argument. The eq fun tion is similar to the equal fun tion in
that it is used to test for equality, but di ers in that it determines whether
two representations are a tually the same obje t inside the omputer, but
with di erent names. equal determines whether the stru ture and ontents
of two expressions are the same.
If the previous ommand was kill-region, then the Ema s Lisp inter-
preter alls the kill-append fun tion

The kill-append fun tion


The kill-append fun tion looks like this:
(defun kill-append (string before-p)
"Append STRING to the end of the latest kill in the kill ring.
If BEFORE-P is non-nil, prepend STRING to the kill.
If `interprogram- ut-fun tion' is set, pass the resulting kill to
it."
(kill-new (if before-p
( on at string ( ar kill-ring))
( on at ( ar kill-ring) string))
t))
The kill-append fun tion is fairly straightforward. It uses the kill-new
fun tion, whi h we will dis uss in more detail in a moment.
First, let us look at the onditional that is one of the two arguments to
kill-new. It uses on at to on atenate the new text to the ar of the kill
ring. Whether it prepends or appends the text depends on the results of an
if expression:
(if before-p ; if-part
( on at string ( ar kill-ring)) ; then-part
( on at ( ar kill-ring) string)) ; else-part
If the region being killed is before the region that was killed in the last
ommand, then it should be prepended before the material that was saved
in the previous kill; and onversely, if the killed text follows what was just
killed, it should be appended after the previous text. The if expression
depends on the predi ate before-p to de ide whether the newly saved text
should be put before or after the previously saved text.
The kill-new fun tion 105

The symbol before-p is the name of one of the arguments to kill-


append. When the kill-append fun tion is evaluated, it is bound to the
value returned by evaluating the a tual argument. In this ase, this is the ex-
pression (< end beg). This expression does not dire tly determine whether
the killed text in this ommand is lo ated before or after the kill text of the
last ommand; what is does is determine whether the value of the variable
end is less than the value of the variable beg. If it is, it means that the
user is most likely heading towards the beginning of the bu er. Also, the
result of evaluating the predi ate expression, (< end beg), will be true and
the text will be prepended before the previous text. On the other hand, if
the value of the variable end is greater than the value of the variable beg,
the text will be appended after the previous text.
When the newly saved text will be prepended, then the string with the
new text will be on atenated before the old text:
( on at string ( ar kill-ring))
But if the text will be appended, it will be on atenated after the old text:
( on at ( ar kill-ring) string))
To understand how this works, we rst need to review the on at fun -
tion. The on at fun tion links together or unites two strings of text. The
result is a string. For example:
( on at "ab " "def")
) "ab def"
( on at "new "
( ar '("first element" "se ond element")))
) "new first element"

( on at ( ar
'("first element" "se ond element")) " modified")
) "first element modified"
We an now make sense of kill-append: it modi es the ontents of the
kill ring. The kill ring is a list, ea h element of whi h is saved text. The
kill-append fun tion uses the kill-new fun tion whi h in turn uses the
set ar fun tion.

The kill-new fun tion


The kill-new fun tion looks like this:
(defun kill-new (string &optional repla e)
"Make STRING the latest kill in the kill ring.
Set the kill-ring-yank pointer to point to it.
If `interprogram- ut-fun tion' is non-nil, apply it to STRING.
Optional se ond argument REPLACE non-nil means that STRING will repla e
the front of the kill ring, rather than being added to the list."
106 Chapter 8: Cutting and Storing Text

(and (fboundp 'menu-bar-update-yank-menu)


(menu-bar-update-yank-menu string (and repla e ( ar kill-ring))))
(if (and repla e kill-ring)
(set ar kill-ring string)
(setq kill-ring ( ons string kill-ring))
(if (> (length kill-ring) kill-ring-max)
(set dr (nth dr (1- kill-ring-max) kill-ring) nil)))
(setq kill-ring-yank-pointer kill-ring)
(if interprogram- ut-fun tion
(fun all interprogram- ut-fun tion string (not repla e))))
As usual, we an look at this fun tion in parts.
The rst line of the do umentation makes sense:
Make STRING the latest kill in the kill ring.
Let's skip over the rest of the do umentation for the moment.
Also, let's skip over the rst two lines of ode, those involving menu-bar-
update-yank-menu. We will explain them below.
The riti al lines are these:
(if (and repla e kill-ring)
;; then
(set ar kill-ring string)
;; else
(setq kill-ring ( ons string kill-ring))
(if (> (length kill-ring) kill-ring-max)
;; avoid overly long kill ring
(set dr (nth dr (1- kill-ring-max) kill-ring) nil)))
(setq kill-ring-yank-pointer kill-ring)
(if interprogram- ut-fun tion
(fun all interprogram- ut-fun tion string (not repla e))))
The onditional test is (and repla e kill-ring). This will be true when
two onditions are met: the kill ring has something in it, and the repla e
variable is true.
The kill-append fun tion sets repla e to be true; then, when the kill
ring has at least one item in it, the set ar expression is exe uted:
(set ar kill-ring string)
The set ar fun tion a tually hanges the rst element of the kill-ring
list to the value of string. It repla es the rst element.
On the other hand, if the kill ring is empty, or repla e is false, the else-part
of the ondition is exe uted:
(setq kill-ring ( ons string kill-ring))
(if (> (length kill-ring) kill-ring-max)
(set dr (nth dr (1- kill-ring-max) kill-ring) nil))
The kill-new fun tion 107

This expression rst onstru ts a new version of the kill ring by prepending
string to the existing kill ring as a new element. Then it exe utes a se ond
if lause. This se ond if lause keeps the kill ring from growing too long.
Let's look at these two expressions in order.
The setq line of the else-part sets the new value of the kill ring to what
results from adding the string being killed to the old kill ring.
We an see how this works with an example:
(setq example-list '("here is a lause" "another lause"))
After evaluating this expression with C-x C-e, you an evaluate example-
list and see what it returns:
example-list
) ("here is a lause" "another lause")
Now, we an add a new element on to this list by evaluating the following
expression:
(setq example-list ( ons "a third lause" example-list))
When we evaluate example-list, we nd its value is:
example-list
) ("a third lause" "here is a lause" "another lause")
Thus, the third lause was added to the list by ons.
This is exa tly similar to what the setq and ons do in the fun tion.
Here is the line again:
(setq kill-ring ( ons string kill-ring))
Now for the se ond part of the if lause. This expression keeps the kill
ring from growing too long. It looks like this:
(if (> (length kill-ring) kill-ring-max)
(set dr (nth dr (1- kill-ring-max) kill-ring) nil))
The ode he ks whether the length of the kill ring is greater than the
maximum permitted length. This is the value of kill-ring-max (whi h is
60, by default). If the length of the kill ring is too long, then this ode sets
the last element of the kill ring to nil. It does this by using two fun tions,
nth dr and set dr.
We looked at set dr earlier (see Se tion 7.6, \set dr", page 88). It sets
the dr of a list, just as set ar sets the ar of a list. In this ase, however,
set dr will not be setting the dr of the whole kill ring; the nth dr fun tion
is used to ause it to set the dr of the next to last element of the kill ring|
this means that sin e the dr of the next to last element is the last element
of the kill ring, it will set the last element of the kill ring.
The nth dr fun tion works by repeatedly taking the dr of a list|it
takes the dr of the dr of the dr . . . It does this N times and returns
the results.
108 Chapter 8: Cutting and Storing Text

Thus, if we had a four element list that was supposed to be three elements
long, we ould set the dr of the next to last element to nil, and thereby
shorten the list.
You an see this by evaluating the following three expressions in turn.
First set the value of trees to (maple oak pine bir h), then set the dr
of its se ond dr to nil and then nd the value of trees:
(setq trees '(maple oak pine bir h))
) (maple oak pine bir h)
(set dr (nth dr 2 trees) nil)
) nil

trees
) (maple oak pine)
(The value returned by the set dr expression is nil sin e that is what the
dr is set to.)
To repeat, in kill-new, the nth dr fun tion takes the dr a number of
times that is one less than the maximum permitted size of the kill ring and
sets the dr of that element (whi h will be the rest of the elements in the
kill ring) to nil. This prevents the kill ring from growing too long.
The next to last expression in the kill-new fun tion is
(setq kill-ring-yank-pointer kill-ring)
The kill-ring-yank-pointer is a global variable that is set to be the
kill-ring.
Even though the kill-ring-yank-pointer is alled a `pointer', it is
a variable just like the kill ring. However, the name has been hosen to
help humans understand how the variable is used. The variable is used in
fun tions su h as yank and yank-pop (see Chapter 10, \Yanking Text Ba k",
page 117).
Now, to return to the rst two lines in the body of the fun tion:
(and (fboundp 'menu-bar-update-yank-menu)
(menu-bar-update-yank-menu string (and repla e ( ar kill-ring))))
This is an expression whose rst element is the fun tion and.
The and spe ial form evaluates ea h of its arguments until one of the
arguments returns a value of nil, in whi h ase the and expression returns
nil; however, if none of the arguments returns a value of nil, the value
resulting from evaluating the last argument is returned. (Sin e su h a value
is not nil, it is onsidered true in Ema s Lisp.) In other words, an and
expression returns a true value only if all its arguments are true.
In this ase, the expression tests rst to see whether menu-bar-update-
yank-menu exists as a fun tion, and if so, alls it. The fboundp fun tion
returns true if the symbol it is testing has a fun tion de nition that `is not
void'. If the symbol's fun tion de nition were void, we would re eive an error
Review 109

message, as we did when we reated errors intentionally (see Se tion 1.3,


\Generate an Error Message", page 4).
Essentially, the and is an if expression that reads like this:
if the-menu-bar-fun tion-exists
then exe ute-it
menu-bar-update-yank-menu is one of the fun tions that make it possi-
ble to use the `Sele t and Paste' menu in the Edit item of a menu bar; using
a mouse, you an look at the various pie es of text you have saved and sele t
one pie e to paste.
Finally, the last expression in the kill-new fun tion adds the newly
opied string to whatever fa ility exists for opying and pasting among dif-
ferent programs running in a windowing system. In the X Windowing sys-
tem, for example, the x-sele t-text fun tion takes the string and stores
it in memory operated by X. You an paste the string in another program,
su h as an Xterm.
The expression looks like this:
(if interprogram- ut-fun tion
(fun all interprogram- ut-fun tion string (not repla e))))
If an interprogram- ut-fun tion exists, then Ema s exe utes fun all,
whi h in turn alls its rst argument as a fun tion and passes the remaining
arguments to it. (In identally, as far as I an see, this if expression ould
be repla ed by an and expression similar to the one in the rst part of the
fun tion.)
We are not going to dis uss windowing systems and other programs fur-
ther, but merely note that this is a me hanism that enables GNU Ema s to
work easily and well with other programs.
This ode for pla ing text in the kill ring, either on atenated with an
existing element or as a new element, leads us to the ode for bringing ba k
text that has been ut out of the bu er|the yank ommands. However,
before dis ussing the yank ommands, it is better to learn how lists are
implemented in a omputer. This will make lear su h mysteries as the use
of the term `pointer'.

8.6 Review
Here is a brief summary of some re ently introdu ed fun tions.
ar
dr ar returns the rst element of a list; dr returns the se ond
and subsequent elements of a list.
110 Chapter 8: Cutting and Storing Text

For example:
( ar '(1 2 3 4 5 6 7))
) 1
( dr '(1 2 3 4 5 6 7))
) (2 3 4 5 6 7)

ons ons onstru ts a list by prepending its rst argument to its


se ond argument.
For example:
( ons 1 '(2 3 4))
) (1 2 3 4)

nth dr Return the result of taking dr `n' times on a list. The nth dr.
The `rest of the rest', as it were.
For example:
(nth dr 3 '(1 2 3 4 5 6 7))
) (4 5 6 7)
set ar
set dr set ar hanges the rst element of a list; set dr hanges the
se ond and subsequent elements of a list.
For example:
(setq triple '(1 2 3))

(set ar triple '37)

triple
) (37 2 3)

(set dr triple '("foo" "bar"))

triple
) (37 "foo" "bar")

progn Evaluate ea h argument in sequen e and then return the value


of the last.
For example:
(progn 1 2 3 4)
) 4
save-restri tion
Re ord whatever narrowing is in e e t in the urrent bu er, if
any, and restore that narrowing after evaluating the arguments.
sear h-forward
Sear h for a string, and if the string is found, move point.
Sear hing Exer ises 111

Takes four arguments:


1. The string to sear h for.
2. Optionally, the limit of the sear h.
3. Optionally, what to do if the sear h fails, return nil or an
error message.
4. Optionally, how many times to repeat the sear h; if nega-
tive, the sear h goes ba kwards.
kill-region
delete-region
opy-region-as-kill
kill-region uts the text between point and mark from the
bu er and stores that text in the kill ring, so you an get it ba k
by yanking.
delete-and-extra t-region removes the text between point
and mark from the bu er and throws it away. You annot get
it ba k.
opy-region-as-kill opies the text between point and mark
into the kill ring, from whi h you an get it by yanking. The
fun tion does not ut or remove the text from the bu er.

8.7 Sear hing Exer ises


 Write an intera tive fun tion that sear hes for a string. If the sear h
nds the string, leave point after it and display a message that says
\Found!". (Do not use sear h-forward for the name of this fun tion;
if you do, you will overwrite the existing version of sear h-forward
that omes with Ema s. Use a name su h as test-sear h instead.)
 Write a fun tion that prints the third element of the kill ring in the e ho
area, if any; if the kill ring does not ontain a third element, print an
appropriate message.
112 Chapter 8: Cutting and Storing Text
How Lists are Implemented 113

9 How Lists are Implemented


In Lisp, atoms are re orded in a straightforward fashion; if the implemen-
tation is not straightforward in pra ti e, it is, nonetheless, straightforward
in theory. The atom `rose', for example, is re orded as the four ontiguous
letters `r', `o', `s', `e'. A list, on the other hand, is kept di erently. The
me hanism is equally simple, but it takes a moment to get used to the idea.
A list is kept using a series of pairs of pointers. In the series, the rst pointer
in ea h pair points to an atom or to another list, and the se ond pointer in
ea h pair points to the next pair, or to the symbol nil, whi h marks the end
of the list.
A pointer itself is quite simply the ele troni address of what is pointed
to. Hen e, a list is kept as a series of ele troni addresses.
For example, the list (rose violet butter up) has three elements,
`rose', `violet', and `butter up'. In the omputer, the ele troni address
of `rose' is re orded in a segment of omputer memory along with the ad-
dress that gives the ele troni address of where the atom `violet' is lo ated;
and that address (the one that tells where `violet' is lo ated) is kept along
with an address that tells where the address for the atom `butter up' is
lo ated.
This sounds more ompli ated than it is and is easier seen in a diagram:

nil

rose violet buttercup

In the diagram, ea h box represents a word of omputer memory that holds


a Lisp obje t, usually in the form of a memory address. The boxes, i.e.
the addresses, are in pairs. Ea h arrow points to what the address is the
address of, either an atom or another pair of addresses. The rst box is the
ele troni address of `rose' and the arrow points to `rose'; the se ond box
is the address of the next pair of boxes, the rst part of whi h is the address
of `violet' and the se ond part of whi h is the address of the next pair. The
very last box points to the symbol nil, whi h marks the end of the list.
When a variable is set to a list with a fun tion su h as setq, it stores the
address of the rst box in the variable. Thus, evaluation of the expression
(setq bouquet '(rose violet butter up))
114 Chapter 9: How Lists are Implemented

reates a situation like this:

bouquet

nil

rose violet buttercup

In this example, the symbol bouquet holds the address of the rst pair of
boxes.
This same list an be illustrated in a di erent sort of box notation like
this:

bouquet

car cdr car cdr car cdr


rose violet butter- nil
cup

(Symbols onsist of more than pairs of addresses, but the stru ture of
a symbol is made up of addresses. Indeed, the symbol bouquet onsists of
a group of address-boxes, one of whi h is the address of the printed word
`bouquet', a se ond of whi h is the address of a fun tion de nition atta hed
to the symbol, if any, a third of whi h is the address of the rst pair of
address-boxes for the list (rose violet butter up), and so on. Here we
are showing that the symbol's third address-box points to the rst pair of
address-boxes for the list.)
If a symbol is set to the dr of a list, the list itself is not hanged; the
symbol simply has an address further down the list. (In the jargon, ar and
dr are `non-destru tive'.) Thus, evaluation of the following expression
(setq flowers ( dr bouquet))
produ es this:

bouquet flowers

nil

rose violet buttercup


Symbols as a Chest of Drawers 115

The value of flowers is (violet butter up), whi h is to say, the symbol
flowers holds the address of the pair of address-boxes, the rst of whi h
holds the address of violet, and the se ond of whi h holds the address of
butter up.
A pair of address-boxes is alled a ons ell or dotted pair. See se tion
\List Type " in The GNU Ema s Lisp Referen e Manual, and se tion \Dot-
ted Pair Notation" in The GNU Ema s Lisp Referen e Manual, for more
information about ons ells and dotted pairs.
The fun tion ons adds a new pair of addresses to the front of a series of
addresses like that shown above. For example, evaluating the expression
(setq bouquet ( ons 'lily bouquet))
produ es:

bouquet flowers

nil
buttercup
lily violet
rose

However, this does not hange the value of the symbol flowers, as you an
see by evaluating the following,
(eq ( dr ( dr bouquet)) flowers)
whi h returns t for true.
Until it is reset, flowers still has the value (violet butter up); that
is, it has the address of the ons ell whose rst address is of violet. Also,
this does not alter any of the pre-existing ons ells; they are all still there.
Thus, in Lisp, to get the dr of a list, you just get the address of the
next ons ell in the series; to get the ar of a list, you get the address of
the rst element of the list; to ons a new element on a list, you add a new
ons ell to the front of the list. That is all there is to it! The underlying
stru ture of Lisp is brilliantly simple!
And what does the last address in a series of ons ells refer to? It is the
address of the empty list, of nil.
In summary, when a Lisp variable is set to a value, it is provided with
the address of the list to whi h the variable refers.

9.1 Symbols as a Chest of Drawers


In an earlier se tion, I suggested that you might imagine a symbol as
being a hest of drawers. The fun tion de nition is put in one drawer, the
116 Chapter 9: How Lists are Implemented

value in another, and so on. What is put in the drawer holding the value an
be hanged without a e ting the ontents of the drawer holding the fun tion
de nition, and vi e-versa.
A tually, what is put in ea h drawer is the address of the value or fun tion
de nition. It is as if you found an old hest in the atti , and in one of its
drawers you found a map giving you dire tions to where the buried treasure
lies.
(In addition to its name, symbol de nition, and variable value, a symbol
has a `drawer' for a property list whi h an be used to re ord other infor-
mation. Property lists are not dis ussed here; see se tion \Property Lists"
in The GNU Ema s Lisp Referen e Manual.)
Here is a fan iful representation:

Chest of Drawers Contents of Drawers

directions to map to
symbol name bouquet

directions to
symbol definition [none]

directions to map to
variable name (rose violet buttercup)

directions to
property list [not described here]

9.2 Exer ise


Set flowers to violet and butter up. Cons two more owers on to this
list and set this new list to more-flowers. Set the ar of flowers to a sh.
What does the more-flowers list now ontain?
The kill-ring-yank-pointer Variable 117

10 Yanking Text Ba k
Whenever you ut text out of a bu er with a `kill' ommand in GNU
Ema s, you an bring it ba k with a `yank' ommand. The text that is ut
out of the bu er is put in the kill ring and the yank ommands insert the
appropriate ontents of the kill ring ba k into a bu er (not ne essarily the
original bu er).
A simple C-y (yank) ommand inserts the rst item from the kill ring into
the urrent bu er. If the C-y ommand is followed immediately by M-y, the
rst element is repla ed by the se ond element. Su essive M-y ommands
repla e the se ond element with the third, fourth, or fth element, and so
on. When the last element in the kill ring is rea hed, it is repla ed by the
rst element and the y le is repeated. (Thus the kill ring is alled a `ring'
rather than just a `list'. However, the a tual data stru ture that holds the
text is a list. See Appendix B, \Handling the Kill Ring", page 243, for the
details of how the list is handled as a ring.)

10.1 Kill Ring Overview


The kill ring is a list of textual strings. This is what it looks like:
("some text" "a different pie e of text" "yet more text")
If this were the ontents of my kill ring and I pressed C-y, the string
of hara ters saying `some text' would be inserted in this bu er where my
ursor is lo ated.
The yank ommand is also used for dupli ating text by opying it. The
opied text is not ut from the bu er, but a opy of it is put on the kill ring
and is inserted by yanking it ba k.
Three fun tions are used for bringing text ba k from the kill ring: yank,
whi h is usually bound to C-y; yank-pop, whi h is usually bound to M-y;
and rotate-yank-pointer, whi h is used by the two other fun tions.
These fun tions refer to the kill ring through a variable alled the kill-
ring-yank-pointer. Indeed, the insertion ode for both the yank and yank-
pop fun tions is:
(insert ( ar kill-ring-yank-pointer))
To begin to understand how yank and yank-pop work, it is rst ne essary
to look at the kill-ring-yank-pointer variable and the rotate-yank-
pointer fun tion.

10.2 The kill-ring-yank-pointer Variable


kill-ring-yank-pointer is a variable, just as kill-ring is a variable.
It points to something by being bound to the value of what it points to, like
any other Lisp variable.
118 Chapter 10: Yanking Text Ba k

Thus, if the value of the kill ring is:


("some text" "a different pie e of text" "yet more text")
and the kill-ring-yank-pointer points to the se ond lause, the value of
kill-ring-yank-pointer is:
("a different pie e of text" "yet more text")
As explained in the previous hapter (see Chapter 9, \List Implementa-
tion", page 113), the omputer does not keep two di erent opies of the text
being pointed to by both the kill-ring and the kill-ring-yank-pointer.
The words \a di erent pie e of text" and \yet more text" are not dupli ated.
Instead, the two Lisp variables point to the same pie es of text. Here is a
diagram:

kill-ring kill-ring-yank-pointer

nil
yet more text
a different piece of text
some text

Both the variable kill-ring and the variable kill-ring-yank-pointer


are pointers. But the kill ring itself is usually des ribed as if it were a tually
what it is omposed of. The kill-ring is spoken of as if it were the list
rather than that it points to the list. Conversely, the kill-ring-yank-
pointer is spoken of as pointing to a list.
These two ways of talking about the same thing sound onfusing at rst
but make sense on re e tion. The kill ring is generally thought of as the
omplete stru ture of data that holds the information of what has re ently
been ut out of the Ema s bu ers. The kill-ring-yank-pointer on the
other hand, serves to indi ate|that is, to `point to'|that part of the kill
ring of whi h the rst element (the ar) will be inserted.
The rotate-yank-pointer fun tion hanges the element in the kill ring
to whi h the kill-ring-yank-pointer points; when the pointer is set to
point to the next element beyond the end of the kill ring, it automati ally
sets it to point to the rst element of the kill ring. This is how the list
is transformed into a ring. The rotate-yank-pointer fun tion itself is not
diÆ ult, but ontains many details. It and the mu h simpler yank and yank-
pop fun tions are des ribed in an appendix. See Appendix B, \Handling the
Kill Ring", page 243.
Exer ises with yank and nth dr 119

10.3 Exer ises with yank and nth dr


 Using C-h v (des ribe-variable), look at the value of your kill ring.
Add several items to your kill ring; look at its value again. Using M-y
(yank-pop), move all the way around the kill ring. How many items
were in your kill ring? Find the value of kill-ring-max. Was your kill
ring full, or ould you have kept more blo ks of text within it?
 Using nth dr and ar, onstru t a series of expressions to return the
rst, se ond, third, and fourth elements of a list.
120 Chapter 10: Yanking Text Ba k
while 121

11 Loops and Re ursion


Ema s Lisp has two primary ways to ause an expression, or a series
of expressions, to be evaluated repeatedly: one uses a while loop, and the
other uses re ursion.
Repetition an be very valuable. For example, to move forward four
senten es, you need only write a program that will move forward one senten e
and then repeat the pro ess four times. Sin e a omputer does not get bored
or tired, su h repetitive a tion does not have the deleterious e e ts that
ex essive or the wrong kinds of repetition an have on humans.
People mostly write Ema s Lisp fun tions using while loops and their
kin; but you an use re ursion, whi h provides a very powerful way to think
about and then to solve problems1.

11.1 while
The while spe ial form tests whether the value returned by evaluating
its rst argument is true or false. This is similar to what the Lisp interpreter
does with an if; what the interpreter does next, however, is di erent.
In a while expression, if the value returned by evaluating the rst argu-
ment is false, the Lisp interpreter skips the rest of the expression (the body
of the expression) and does not evaluate it. However, if the value is true, the
Lisp interpreter evaluates the body of the expression and then again tests
whether the rst argument to while is true or false. If the value returned
by evaluating the rst argument is again true, the Lisp interpreter again
evaluates the body of the expression.
The template for a while expression looks like this:
(while true-or-false-test
body ...)
So long as the true-or-false-test of the while expression returns a true
value when it is evaluated, the body is repeatedly evaluated. This pro ess
is alled a loop sin e the Lisp interpreter repeats the same thing again and
again, like an airplane doing a loop. When the result of evaluating the true-
or-false-test is false, the Lisp interpreter does not evaluate the rest of the
while expression and `exits the loop'.
Clearly, if the value returned by evaluating the rst argument to while
is always true, the body following will be evaluated again and again . . .
and again . . . forever. Conversely, if the value returned is never true, the
1 You an write re ursive fun tions to be frugal or wasteful of mental or omputer
resour es; as it happens, methods that people nd easy|that are frugal of `mental
resour es'|sometimes use onsiderable omputer resour es. Ema s was designed to
run on ma hines that we now onsider limited and its default settings are onservative.
You may want to in rease the values of max-spe pdl-size and max-lisp-eval-depth.
In my `.ema s' le, I set them to 15 and 30 times their default value.
122 Chapter 11: Loops and Re ursion

expressions in the body will never be evaluated. The raft of writing a while
loop onsists of hoosing a me hanism su h that the true-or-false-test returns
true just the number of times that you want the subsequent expressions to
be evaluated, and then have the test return false.
The value returned by evaluating a while is the value of the true-or-false-
test. An interesting onsequen e of this is that a while loop that evaluates
without error will return nil or false regardless of whether it has looped 1 or
100 times or none at all. A while expression that evaluates su essfully never
returns a true value! What this means is that while is always evaluated for
its side e e ts, whi h is to say, the onsequen es of evaluating the expressions
within the body of the while loop. This makes sense. It is not the mere a t
of looping that is desired, but the onsequen es of what happens when the
expressions in the loop are repeatedly evaluated.

11.1.1 A while Loop and a List


A ommon way to ontrol a while loop is to test whether a list has any
elements. If it does, the loop is repeated; but if it does not, the repetition is
ended. Sin e this is an important te hnique, we will reate a short example
to illustrate it.
A simple way to test whether a list has elements is to evaluate the list:
if it has no elements, it is an empty list and will return the empty list, (),
whi h is a synonym for nil or false. On the other hand, a list with elements
will return those elements when it is evaluated. Sin e Ema s Lisp onsiders
as true any value that is not nil, a list that returns elements will test true
in a while loop.
For example, you an set the variable empty-list to nil by evaluating
the following setq expression:
(setq empty-list ())
After evaluating the setq expression, you an evaluate the variable empty-
list in the usual way, by pla ing the ursor after the symbol and typing
C-x C-e; nil will appear in your e ho area:
empty-list
On the other hand, if you set a variable to be a list with elements, the
list will appear when you evaluate the variable, as you an see by evaluating
the following two expressions:
(setq animals '(gazelle giraffe lion tiger))

animals
Thus, to reate a while loop that tests whether there are any items in
the list animals, the rst part of the loop will be written like this:
(while animals
...
An Example: print-elements-of-list 123

When the while tests its rst argument, the variable animals is evaluated.
It returns a list. So long as the list has elements, the while onsiders the
results of the test to be true; but when the list is empty, it onsiders the
results of the test to be false.
To prevent the while loop from running forever, some me hanism needs
to be provided to empty the list eventually. An oft-used te hnique is to have
one of the subsequent forms in the while expression set the value of the list
to be the dr of the list. Ea h time the dr fun tion is evaluated, the list
will be made shorter, until eventually only the empty list will be left. At
this point, the test of the while loop will return false, and the arguments to
the while will no longer be evaluated.
For example, the list of animals bound to the variable animals an be
set to be the dr of the original list with the following expression:
(setq animals ( dr animals))
If you have evaluated the previous expressions and then evaluate this ex-
pression, you will see (giraffe lion tiger) appear in the e ho area. If you
evaluate the expression again, (lion tiger) will appear in the e ho area. If
you evaluate it again and yet again, (tiger) appears and then the empty
list, shown by nil.
A template for a while loop that uses the dr fun tion repeatedly to
ause the true-or-false-test eventually to test false looks like this:
(while test-whether-list-is-empty
body ...
set-list-to- dr-of-list)
This test and use of dr an be put together in a fun tion that goes
through a list and prints ea h element of the list on a line of its own.

11.1.2 An Example: print-elements-of-list


The print-elements-of-list fun tion illustrates a while loop with a
list.
The fun tion requires several lines for its output. If you are reading this
in Ema s 21 or a later version, you an evaluate the following expression
inside of Info, as usual.
If you are using an earlier version of Ema s, you need to opy the ne es-
sary expressions to your `*s rat h*' bu er and evaluate them there. This
is be ause the e ho area had only one line in the earlier versions.
You an opy the expressions by marking the beginning of the region with
C-hSPCi (set-mark- ommand), moving the ursor to the end of the region
and then opying the region using M-w ( opy-region-as-kill). In the
`*s rat h*' bu er, you an yank the expressions ba k by typing C-y (yank).
After you have opied the expressions to the `*s rat h*' bu er, evaluate
ea h expression in turn. Be sure to evaluate the last expression, (print-
elements-of-list animals), by typing C-u C-x C-e, that is, by giving an
124 Chapter 11: Loops and Re ursion

argument to eval-last-sexp. This will ause the result of the evalua-


tion to be printed in the `*s rat h*' bu er instead of being printed in
the e ho area. (Otherwise you will see something like this in your e ho
area: ^Jgiraffe^J^Jgazelle^J^Jlion^J^Jtiger^Jnil, in whi h ea h `^J'
stands for a `newline'.)
If you are using Ema s 21 or later, you an evaluate these expressions
dire tly in the Info bu er, and the e ho area will grow to show the results.
(setq animals '(gazelle giraffe lion tiger))

(defun print-elements-of-list (list)


"Print ea h element of LIST on a line of its own."
(while list
(print ( ar list))
(setq list ( dr list))))

(print-elements-of-list animals)
When you evaluate the three expressions in sequen e, you will see this:
giraffe

gazelle

lion

tiger
nil
Ea h element of the list is printed on a line of its own (that is what the
fun tion print does) and then the value returned by the fun tion is printed.
Sin e the last expression in the fun tion is the while loop, and sin e while
loops always return nil, a nil is printed after the last element of the list.

11.1.3 A Loop with an In rementing Counter


A loop is not useful unless it stops when it ought. Besides ontrolling
a loop with a list, a ommon way of stopping a loop is to write the rst
argument as a test that returns false when the orre t number of repetitions
are omplete. This means that the loop must have a ounter|an expression
that ounts how many times the loop repeats itself.
The test an be an expression su h as (< ount desired-number) whi h
returns t for true if the value of ount is less than the desired-number of
repetitions and nil for false if the value of ount is equal to or is greater
than the desired-number. The expression that in rements the ount an
be a simple setq su h as (setq ount (1+ ount)), where 1+ is a built-
in fun tion in Ema s Lisp that adds 1 to its argument. (The expression
Example with in rementing ounter 125

(1+ ount) has the same result as (+ ount 1), but is easier for a human
to read.)
The template for a while loop ontrolled by an in rementing ounter
looks like this:
set- ount-to-initial-value
(while (< ount desired-number) ; true-or-false-test
body ...
(setq ount (1+ ount))) ; in rementer
Note that you need to set the initial value of ount; usually it is set to 1.

Example with in rementing ounter


Suppose you are playing on the bea h and de ide to make a triangle of
pebbles, putting one pebble in the rst row, two in the se ond row, three in
the third row and so on, like this:

 
  
   

(About 2500 years ago, Pythagoras and others developed the beginnings of
number theory by onsidering questions su h as this.)
Suppose you want to know how many pebbles you will need to make a
triangle with 7 rows?
Clearly, what you need to do is add up the numbers from 1 to 7. There
are two ways to do this; start with the smallest number, one, and add up
the list in sequen e, 1, 2, 3, 4 and so on; or start with the largest number
and add the list going down: 7, 6, 5, 4 and so on. Be ause both me hanisms
illustrate ommon ways of writing while loops, we will reate two examples,
one ounting up and the other ounting down. In this rst example, we will
start with 1 and add 2, 3, 4 and so on.
If you are just adding up a short list of numbers, the easiest way to do it
is to add up all the numbers at on e. However, if you do not know ahead of
time how many numbers your list will have, or if you want to be prepared
for a very long list, then you need to design your addition so that what you
do is repeat a simple pro ess many times instead of doing a more omplex
pro ess on e.
For example, instead of adding up all the pebbles all at on e, what you
an do is add the number of pebbles in the rst row, 1, to the number in the
se ond row, 2, and then add the total of those two rows to the third row, 3.
Then you an add the number in the fourth row, 4, to the total of the rst
three rows; and so on.
126 Chapter 11: Loops and Re ursion

The riti al hara teristi of the pro ess is that ea h repetitive a tion is
simple. In this ase, at ea h step we add only two numbers, the number of
pebbles in the row and the total already found. This pro ess of adding two
numbers is repeated again and again until the last row has been added to
the total of all the pre eding rows. In a more omplex loop the repetitive
a tion might not be so simple, but it will be simpler than doing everything
all at on e.

The parts of the fun tion de nition


The pre eding analysis gives us the bones of our fun tion de nition: rst,
we will need a variable that we an all total that will be the total number
of pebbles. This will be the value returned by the fun tion.
Se ond, we know that the fun tion will require an argument: this ar-
gument will be the total number of rows in the triangle. It an be alled
number-of-rows.
Finally, we need a variable to use as a ounter. We ould all this vari-
able ounter, but a better name is row-number. That is be ause what
the ounter does is ount rows, and a program should be written to be as
understandable as possible.
When the Lisp interpreter rst starts evaluating the expressions in the
fun tion, the value of total should be set to zero, sin e we have not added
anything to it. Then the fun tion should add the number of pebbles in the
rst row to the total, and then add the number of pebbles in the se ond to
the total, and then add the number of pebbles in the third row to the total,
and so on, until there are no more rows left to add.
Both total and row-number are used only inside the fun tion, so they
an be de lared as lo al variables with let and given initial values. Clearly,
the initial value for total should be 0. The initial value of row-number
should be 1, sin e we start with the rst row. This means that the let
statement will look like this:
(let ((total 0)
(row-number 1))
body ...)
After the internal variables are de lared and bound to their initial values,
we an begin the while loop. The expression that serves as the test should
return a value of t for true so long as the row-number is less than or equal
to the number-of-rows. (If the expression tests true only so long as the
row number is less than the number of rows in the triangle, the last row will
never be added to the total; hen e the row number has to be either less than
or equal to the number of rows.)
Putting the fun tion de nition together 127

Lisp provides the <= fun tion that returns true if the value of its rst
argument is less than or equal to the value of its se ond argument and false
otherwise. So the expression that the while will evaluate as its test should
look like this:
(<= row-number number-of-rows)
The total number of pebbles an be found by repeatedly adding the num-
ber of pebbles in a row to the total already found. Sin e the number of
pebbles in the row is equal to the row number, the total an be found by
adding the row number to the total. (Clearly, in a more omplex situation,
the number of pebbles in the row might be related to the row number in
a more ompli ated way; if this were the ase, the row number would be
repla ed by the appropriate expression.)
(setq total (+ total row-number))
What this does is set the new value of total to be equal to the sum of
adding the number of pebbles in the row to the previous total.
After setting the value of total, the onditions need to be established for
the next repetition of the loop, if there is one. This is done by in rementing
the value of the row-number variable, whi h serves as a ounter. After
the row-number variable has been in remented, the true-or-false-test at the
beginning of the while loop tests whether its value is still less than or equal
to the value of the number-of-rows and if it is, adds the new value of the
row-number variable to the total of the previous repetition of the loop.
The built-in Ema s Lisp fun tion 1+ adds 1 to a number, so the row-
number variable an be in remented with this expression:
(setq row-number (1+ row-number))

Putting the fun tion de nition together


We have reated the parts for the fun tion de nition; now we need to put
them together.
First, the ontents of the while expression:
(while (<= row-number number-of-rows) ; true-or-false-test
(setq total (+ total row-number))
(setq row-number (1+ row-number))) ; in rementer
Along with the let expression varlist, this very nearly ompletes the body
of the fun tion de nition. However, it requires one nal element, the need
for whi h is somewhat subtle.
The nal tou h is to pla e the variable total on a line by itself after the
while expression. Otherwise, the value returned by the whole fun tion is
the value of the last expression that is evaluated in the body of the let, and
this is the value returned by the while, whi h is always nil.
This may not be evident at rst sight. It almost looks as if the in re-
menting expression is the last expression of the whole fun tion. But that
128 Chapter 11: Loops and Re ursion

expression is part of the body of the while; it is the last element of the list
that starts with the symbol while. Moreover, the whole of the while loop
is a list within the body of the let.
In outline, the fun tion will look like this:
(defun name-of-fun tion (argument-list)
"do umentation..."
(let (varlist)
(while (true-or-false-test)
body-of-while ... )
... ) ; Need nal expression here.

The result of evaluating the let is what is going to be returned by the


defun sin e the let is not embedded within any ontaining list, ex ept for
the defun as a whole. However, if the while is the last element of the let
expression, the fun tion will always return nil. This is not what we want!
Instead, what we want is the value of the variable total. This is returned
by simply pla ing the symbol as the last element of the list starting with
let. It gets evaluated after the pre eding elements of the list are evaluated,
whi h means it gets evaluated after it has been assigned the orre t value
for the total.
It may be easier to see this by printing the list starting with let all on one
line. This format makes it evident that the varlist and while expressions are
the se ond and third elements of the list starting with let, and the total
is the last element:
(let (varlist) (while (true-or-false-test) body-of-while ... ) total)

Putting everything together, the triangle fun tion de nition looks like
this:
(defun triangle (number-of-rows) ; Version with
; in rementing ounter.
"Add up the number of pebbles in a triangle.
The first row has one pebble, the se ond row two pebbles,
the third row three pebbles, and so on.
The argument is NUMBER-OF-ROWS."
(let ((total 0)
(row-number 1))
(while (<= row-number number-of-rows)
(setq total (+ total row-number))
(setq row-number (1+ row-number)))
total))
Example with de rementing ounter 129

After you have installed triangle by evaluating the fun tion, you an
try it out. Here are two examples:
(triangle 4)

(triangle 7)
The sum of the rst four numbers is 10 and the sum of the rst seven numbers
is 28.

11.1.4 Loop with a De rementing Counter


Another ommon way to write a while loop is to write the test so that
it determines whether a ounter is greater than zero. So long as the ounter
is greater than zero, the loop is repeated. But when the ounter is equal to
or less than zero, the loop is stopped. For this to work, the ounter has to
start out greater than zero and then be made smaller and smaller by a form
that is evaluated repeatedly.
The test will be an expression su h as (> ounter 0) whi h returns t
for true if the value of ounter is greater than zero, and nil for false if the
value of ounter is equal to or less than zero. The expression that makes the
number smaller and smaller an be a simple setq su h as (setq ounter
(1- ounter)), where 1- is a built-in fun tion in Ema s Lisp that subtra ts
1 from its argument.
The template for a de rementing while loop looks like this:
(while (> ounter 0) ; true-or-false-test
body ...
(setq ounter (1- ounter))) ; de rementer

Example with de rementing ounter


To illustrate a loop with a de rementing ounter, we will rewrite the
triangle fun tion so the ounter de reases to zero.
This is the reverse of the earlier version of the fun tion. In this ase, to
nd out how many pebbles are needed to make a triangle with 3 rows, add
the number of pebbles in the third row, 3, to the number in the pre eding
row, 2, and then add the total of those two rows to the row that pre edes
them, whi h is 1.
Likewise, to nd the number of pebbles in a triangle with 7 rows, add the
number of pebbles in the seventh row, 7, to the number in the pre eding row,
whi h is 6, and then add the total of those two rows to the row that pre edes
them, whi h is 5, and so on. As in the previous example, ea h addition only
involves adding two numbers, the total of the rows already added up and the
number of pebbles in the row that is being added to the total. This pro ess
of adding two numbers is repeated again and again until there are no more
pebbles to add.
130 Chapter 11: Loops and Re ursion

We know how many pebbles to start with: the number of pebbles in the
last row is equal to the number of rows. If the triangle has seven rows, the
number of pebbles in the last row is 7. Likewise, we know how many pebbles
are in the pre eding row: it is one less than the number in the row.

The parts of the fun tion de nition


We start with three variables: the total number of rows in the triangle;
the number of pebbles in a row; and the total number of pebbles, whi h is
what we want to al ulate. These variables an be named number-of-rows,
number-of-pebbles-in-row, and total, respe tively.
Both total and number-of-pebbles-in-row are used only inside the
fun tion and are de lared with let. The initial value of total should, of
ourse, be zero. However, the initial value of number-of-pebbles-in-row
should be equal to the number of rows in the triangle, sin e the addition will
start with the longest row.
This means that the beginning of the let expression will look like this:
(let ((total 0)
(number-of-pebbles-in-row number-of-rows))
body ...)
The total number of pebbles an be found by repeatedly adding the num-
ber of pebbles in a row to the total already found, that is, by repeatedly
evaluating the following expression:
(setq total (+ total number-of-pebbles-in-row))
After the number-of-pebbles-in-row is added to the total, the number-
of-pebbles-in-row should be de remented by one, sin e the next time the
loop repeats, the pre eding row will be added to the total.
The number of pebbles in a pre eding row is one less than the number
of pebbles in a row, so the built-in Ema s Lisp fun tion 1- an be used to
ompute the number of pebbles in the pre eding row. This an be done with
the following expression:
(setq number-of-pebbles-in-row
(1- number-of-pebbles-in-row))
Finally, we know that the while loop should stop making repeated addi-
tions when there are no pebbles in a row. So the test for the while loop is
simply:
(while (> number-of-pebbles-in-row 0)

Putting the fun tion de nition together


We an put these expressions together to reate a fun tion de nition that
works. However, on examination, we nd that one of the lo al variables is
unneeded!
Save your time: dolist and dotimes 131

The fun tion de nition looks like this:


;;; First subtra tive version.
(defun triangle (number-of-rows)
"Add up the number of pebbles in a triangle."
(let ((total 0)
(number-of-pebbles-in-row number-of-rows))
(while (> number-of-pebbles-in-row 0)
(setq total (+ total number-of-pebbles-in-row))
(setq number-of-pebbles-in-row
(1- number-of-pebbles-in-row)))
total))
As written, this fun tion works.
However, we do not need number-of-pebbles-in-row.
When the triangle fun tion is evaluated, the symbol number-of-rows
will be bound to a number, giving it an initial value. That number an be
hanged in the body of the fun tion as if it were a lo al variable, without
any fear that su h a hange will e e t the value of the variable outside of
the fun tion. This is a very useful hara teristi of Lisp; it means that
the variable number-of-rows an be used anywhere in the fun tion where
number-of-pebbles-in-row is used.
Here is a se ond version of the fun tion written a bit more leanly:
(defun triangle (number) ; Se ond version.
"Return sum of numbers 1 through NUMBER in lusive."
(let ((total 0))
(while (> number 0)
(setq total (+ total number))
(setq number (1- number)))
total))
In brief, a properly written while loop will onsist of three parts:
1. A test that will return false after the loop has repeated itself the orre t
number of times.
2. An expression the evaluation of whi h will return the value desired after
being repeatedly evaluated.
3. An expression to hange the value passed to the true-or-false-test so
that the test returns false after the loop has repeated itself the right
number of times.

11.2 Save your time: dolist and dotimes


In addition to while, both dolist and dotimes provide for looping.
Sometimes these are qui ker to write than the equivalent while loop. Both
are Lisp ma ros. (See se tion \Ma ros" in The GNU Ema s Lisp Referen e
Manual. )
132 Chapter 11: Loops and Re ursion

dolist works like a while loop that ` drs down a list': dolist auto-
mati ally shortens the list ea h time it loops|takes the dr of the list|and
binds the ar of ea h shorter version of the list to the rst of its arguments.
dotimes loops a spe i number of time: you spe ify the number.

The dolist Ma ro
Suppose, for example, you want to reverse a list, so that \ rst" \se ond"
\third" be omes \third" \se ond" \ rst".
In pra ti e, you would use the reverse fun tion, like this:
(setq animals '(gazelle giraffe lion tiger))

(reverse animals)
Here is how you ould reverse the list using a while loop:
(setq animals '(gazelle giraffe lion tiger))

(defun reverse-list-with-while (list)


"Using while, reverse the order of LIST."
(let (value) ; make sure list starts empty
(while list
(setq value ( ons ( ar list) value))
(setq list ( dr list)))
value))

(reverse-list-with-while animals)
And here is how you ould use the dolist ma ro:
(setq animals '(gazelle giraffe lion tiger))

(defun reverse-list-with-dolist (list)


"Using dolist, reverse the order of LIST."
(let (value) ; make sure list starts empty
(dolist (element list value)
(setq value ( ons element value)))))

(reverse-list-with-dolist animals)
In Info, you an pla e your ursor after the losing parenthesis of ea h ex-
pression and type C-x C-e; in ea h ase, you should see
(tiger lion giraffe gazelle)
in the e ho area.
For this example, the existing reverse fun tion is obviously best. The
while loop is just like our rst example (see Se tion 11.1.1, \A while Loop
and a List", page 122). The while rst he ks whether the list has elements;
if so, it onstru ts a new list by adding the rst element of the list to the
The dotimes Ma ro 133

existing list (whi h in the rst iteration of the loop is nil). Sin e the se ond
element is prepended in front of the rst element, and the third element is
prepended in front of the se ond element, the list is reversed.
In the expression using a while loop, the (setq list ( dr list)) ex-
pression shortens the list, so the while loop eventually stops. In addition,
it provides the ons expression with a new rst element by reating a new
and shorter list at ea h repetition of the loop.
The dolist expression does very mu h the same as the while expression,
ex ept that the dolist ma ro does some of the work you have to do when
writing a while expression.
Like a while loop, a dolist loops. What is di erent is that it automat-
i ally shortens the list ea h time it loops | it ` drs down the list' on its
own | and it automati ally binds the ar of ea h shorter version of the list
to the rst of its arguments.
In the example, the ar of ea h shorter version of the list is referred
to using the symbol `element', the list itself is alled `list', and the value
returned is alled `value'. The remainder of the dolist expression is the
body.
The dolist expression binds the ar of ea h shorter version of the list
to element and then evaluates the body of the expression; and repeats the
loop. The result is returned in value.

The dotimes Ma ro
The dotimes ma ro is similar to dolist, ex ept that it loops a spe i
number of times.
The rst argument to dotimes is assigned the numbers 0, 1, 2 and so
forth ea h time around the loop, and the value of the third argument is
returned. You need to provide the value of the se ond argument, whi h is
how many times the ma ro loops.
For example, the following binds the numbers from 0 up to, but not
in luding, the number 3 to the rst argument, number, and then onstru ts
a list of the three numbers. (The rst number is 0, the se ond number is
1, and the third number is 2; this makes a total of three numbers in all,
starting with zero as the rst number.)
(let (value) ; otherwise a value is a void variable
(dotimes (number 3 value)
(setq value ( ons number value))))

) (2 1 0)
dotimes returns value, so the way to use dotimes is to operate on some
expression number number of times and then return the result, either as a
list or an atom.
134 Chapter 11: Loops and Re ursion

Here is an example of a defun that uses dotimes to add up the number


of pebbles in a triangle.
(defun triangle-using-dotimes (number-of-rows)
"Using dotimes, add up the number of pebbles in a triangle."
(let ((total 0)) ; otherwise a total is a void variable
(dotimes (number number-of-rows total)
(setq total (+ total (1+ number))))))

(triangle-using-dotimes 4)

11.3 Re ursion
A re ursive fun tion ontains ode that tells the Lisp interpreter to all a
program that runs exa tly like itself, but with slightly di erent arguments.
The ode runs exa tly the same be ause it has the same name. However,
even though it has the same name, it is not the same thread of exe ution.
It is di erent. In the jargon, it is a di erent `instan e'.
Eventually, if the program is written orre tly, the `slightly di erent ar-
guments' will be ome suÆ iently di erent from the rst arguments that the
nal instan e will stop.

11.3.1 Building Robots: Extending the Metaphor


It is sometimes helpful to think of a running program as a robot that does
a job. In doing its job, a re ursive fun tion alls on a se ond robot to help
it. The se ond robot is identi al to the rst in every way, ex ept that the
se ond robot helps the rst and has been passed di erent arguments than
the rst.
In a re ursive fun tion, the se ond robot may all a third; and the third
may all a fourth, and so on. Ea h of these is a di erent entity; but all are
lones.
Sin e ea h robot has slightly di erent instru tions|the arguments will
di er from one robot to the next|the last robot should know when to stop.
Let's expand on the metaphor in whi h a omputer program is a robot.
A fun tion de nition provides the blueprints for a robot. When you install
a fun tion de nition, that is, when you evaluate a defun spe ial form, you
install the ne essary equipment to build robots. It is as if you were in a
fa tory, setting up an assembly line. Robots with the same name are built
a ording to the same blueprints. So they have, as it were, the same `model
number', but a di erent `serial number'.
We often say that a re ursive fun tion ` alls itself'. What we mean is
that the instru tions in a re ursive fun tion ause the Lisp interpreter to
run a di erent fun tion that has the same name and does the same job as
the rst, but with di erent arguments.
Re ursion with a List 135

It is important that the arguments di er from one instan e to the next;


otherwise, the pro ess will never stop.

11.3.2 The Parts of a Re ursive De nition


A re ursive fun tion typi ally ontains a onditional expression whi h has
three parts:
1. A true-or-false-test that determines whether the fun tion is alled again,
here alled the do-again-test.
2. The name of the fun tion. When this name is alled, a new instan e of
the fun tion|a new robot, as it were|is reated and told what to do.
3. An expression that returns a di erent value ea h time the fun tion is
alled, here alled the next-step-expression. Consequently, the argu-
ment (or arguments) passed to the new instan e of the fun tion will
be di erent from that passed to the previous instan e. This auses the
onditional expression, the do-again-test, to test false after the orre t
number of repetitions.
Re ursive fun tions an be mu h simpler than any other kind of fun tion.
Indeed, when people rst start to use them, they often look so mysteriously
simple as to be in omprehensible. Like riding a bi y le, reading a re ursive
fun tion de nition takes a ertain kna k whi h is hard at rst but then seems
simple.
There are several di erent ommon re ursive patterns. A very simple
pattern looks like this:
(defun name-of-re ursive-fun tion (argument-list)
"do umentation..."
(if do-again-test
body ...
(name-of-re ursive-fun tion
next-step-expression)))
Ea h time a re ursive fun tion is evaluated, a new instan e of it is reated
and told what to do. The arguments tell the instan e what to do.
An argument is bound to the value of the next-step-expression. Ea h
instan e runs with a di erent value of the next-step-expression.
The value in the next-step-expression is used in the do-again-test.
The value returned by the next-step-expression is passed to the new in-
stan e of the fun tion, whi h evaluates it (or some transmogri ation of it)
to determine whether to ontinue or stop. The next-step-expression is de-
signed so that the do-again-test returns false when the fun tion should no
longer be repeated.
The do-again-test is sometimes alled the stop ondition, sin e it stops
the repetitions when it tests false.
136 Chapter 11: Loops and Re ursion

11.3.3 Re ursion with a List


The example of a while loop that printed the elements of a list of numbers
an be written re ursively. Here is the ode, in luding an expression to set
the value of the variable animals to a list.
If you are using Ema s 20 or before, this example must be opied to the
`*s rat h*' bu er and ea h expression must be evaluated there. Use C-u C-
x C-e to evaluate the (print-elements-re ursively animals) expression
so that the results are printed in the bu er; otherwise the Lisp interpreter
will try to squeeze the results into the one line of the e ho area.
Also, pla e your ursor immediately after the last losing parenthesis of
the print-elements-re ursively fun tion, before the omment. Other-
wise, the Lisp interpreter will try to evaluate the omment.
If you are using Ema s 21 or later, you an evaluate this expression
dire tly in Info.
(setq animals '(gazelle giraffe lion tiger))

(defun print-elements-re ursively (list)


"Print ea h element of LIST on a line of its own.
Uses re ursion."
(if list ; do-again-test
(progn
(print ( ar list)) ; body
(print-elements-re ursively ; re ursive all
( dr list))))) ; next-step-expression

(print-elements-re ursively animals)


The print-elements-re ursively fun tion rst tests whether there is
any ontent in the list; if there is, the fun tion prints the rst element of the
list, the ar of the list. Then the fun tion `invokes itself', but gives itself as
its argument, not the whole list, but the se ond and subsequent elements of
the list, the dr of the list.
Put another way, if the list is not empty, the fun tion invokes another
instan e of ode that is similar to the initial ode, but is a di erent thread
of exe ution, with di erent arguments than the rst instan e.
Put in yet another way, if the list is not empty, the rst robot assemblies a
se ond robot and tells it what to do; the se ond robot is a di erent individual
from the rst, but is the same model.
When the se ond evaluation o urs, the if expression is evaluated and if
true, prints the rst element of the list it re eives as its argument (whi h is
the se ond element of the original list). Then the fun tion ` alls itself' with
the dr of the list it is invoked with, whi h (the se ond time around) is the
dr of the dr of the original list.
Re ursion in Pla e of a Counter 137

Note that although we say that the fun tion ` alls itself', what we mean
is that the Lisp interpreter assembles and instru ts a new instan e of the
program. The new instan e is a lone of the rst, but is a separate individual.
Ea h time the fun tion `invokes itself', it invokes itself on a shorter version
of the original list. It reates a new instan e that works on a shorter list.
Eventually, the fun tion invokes itself on an empty list. It reates a new
instan e whose argument is nil. The onditional expression tests the value
of list. Sin e the value of list is nil, the if expression tests false so the
then-part is not evaluated. The fun tion as a whole then returns nil.
When you evaluate (print-elements-re ursively animals) in the
`*s rat h*' bu er, you see this result:
giraffe

gazelle

lion

tiger
nil

11.3.4 Re ursion in Pla e of a Counter


The triangle fun tion des ribed in a previous se tion an also be written
re ursively. It looks like this:
(defun triangle-re ursively (number)
"Return the sum of the numbers 1 through NUMBER in lusive.
Uses re ursion."
(if (= number 1) ; do-again-test
1 ; then-part
(+ number ; else-part
(triangle-re ursively ; re ursive all
(1- number))))) ; next-step-expression

(triangle-re ursively 7)
You an install this fun tion by evaluating it and then try it by evaluating
(triangle-re ursively 7). (Remember to put your ursor immediately
after the last parenthesis of the fun tion de nition, before the omment.)
The fun tion evaluates to 28.
To understand how this fun tion works, let's onsider what happens in
the various ases when the fun tion is passed 1, 2, 3, or 4 as the value of its
argument.
First, what happens if the value of the argument is 1?
The fun tion has an if expression after the do umentation string. It
tests whether the value of number is equal to 1; if so, Ema s evaluates the
138 Chapter 11: Loops and Re ursion

then-part of the if expression, whi h returns the number 1 as the value of


the fun tion. (A triangle with one row has one pebble in it.)
Suppose, however, that the value of the argument is 2. In this ase,
Ema s evaluates the else-part of the if expression.
The else-part onsists of an addition, the re ursive all to triangle-
re ursively and a de rementing a tion; and it looks like this:
(+ number (triangle-re ursively (1- number)))
When Ema s evaluates this expression, the innermost expression is eval-
uated rst; then the other parts in sequen e. Here are the steps in detail:
Step 1 Evaluate the innermost expression.
The innermost expression is (1- number) so Ema s de rements
the value of number from 2 to 1.
Step 2 Evaluate the triangle-re ursively fun tion.
The Lisp interpreter reates an individual instan e of triangle-
re ursively. It does not matter that this fun tion is ontained
within itself. Ema s passes the result Step 1 as the argument
used by this instan e of the triangle-re ursively fun tion
In this ase, Ema s evaluates triangle-re ursively with an
argument of 1. This means that this evaluation of triangle-
re ursively returns 1.
Step 3 Evaluate the value of number.
The variable number is the se ond element of the list that starts
with +; its value is 2.
Step 4 Evaluate the + expression.
The + expression re eives two arguments, the rst from the eval-
uation of number (Step 3) and the se ond from the evaluation
of triangle-re ursively (Step 2).
The result of the addition is the sum of 2 plus 1, and the number
3 is returned, whi h is orre t. A triangle with two rows has
three pebbles in it.

An argument of 3 or 4
Suppose that triangle-re ursively is alled with an argument of 3.
Step 1 Evaluate the do-again-test.
The if expression is evaluated rst. This is the do-again test and
returns false, so the else-part of the if expression is evaluated.
(Note that in this example, the do-again-test auses the fun tion
to all itself when it tests false, not when it tests true.)
Step 2 Evaluate the innermost expression of the else-part.
The innermost expression of the else-part is evaluated, whi h
de rements 3 to 2. This is the next-step-expression.
Re ursion Example Using ond 139

Step 3 Evaluate the triangle-re ursively fun tion.


The number 2 is passed to the triangle-re ursively fun tion.
We know what happens when Ema s evaluates triangle-
re ursively with an argument of 2. After going through the
sequen e of a tions des ribed earlier, it returns a value of 3. So
that is what will happen here.
Step 4 Evaluate the addition.
3 will be passed as an argument to the addition and will be
added to the number with whi h the fun tion was alled, whi h
is 3.
The value returned by the fun tion as a whole will be 6.
Now that we know what will happen when triangle-re ursively is
alled with an argument of 3, it is evident what will happen if it is alled
with an argument of 4:
In the re ursive all, the evaluation of
(triangle-re ursively (1- 4))
will return the value of evaluating
(triangle-re ursively 3)
whi h is 6 and this value will be added to 4 by the addition in the
third line.
The value returned by the fun tion as a whole will be 10.
Ea h time triangle-re ursively is evaluated, it evaluates a version
of itself|a di erent instan e of itself|with a smaller argument, until the
argument is small enough so that it does not evaluate itself.
Note that this parti ular design for a re ursive fun tion requires that
operations be deferred.
Before (triangle-re ursively 7) an al ulate its answer, it must all
(triangle-re ursively 6); and before (triangle-re ursively 6) an
al ulate its answer, it must all (triangle-re ursively 5); and so on.
That is to say, the al ulation that (triangle-re ursively 7) makes must
be deferred until (triangle-re ursively 6) makes its al ulation; and
(triangle-re ursively 6) must defer until (triangle-re ursively 5)
ompletes; and so on.
If ea h of these instan es of triangle-re ursively are thought of as
di erent robots, the rst robot must wait for the se ond to omplete its job,
whi h must wait until the third ompletes, and so on.
There is a way around this kind of waiting, whi h we will dis uss in
Se tion 11.3.7, \Re ursion without Deferments", page 143.
11.3.5 Re ursion Example Using ond
The version of triangle-re ursively des ribed earlier is written with
the if spe ial form. It an also be written using another spe ial form alled
140 Chapter 11: Loops and Re ursion

ond. The name of the spe ial form ond is an abbreviation of the word
` onditional'.
Although the ond spe ial form is not used as often in the Ema s Lisp
sour es as if, it is used often enough to justify explaining it.
The template for a ond expression looks like this:
( ond
body ...)
where the body is a series of lists.
Written out more fully, the template looks like this:
( ond
( rst-true-or-false-test rst- onsequent)
(se ond-true-or-false-test se ond- onsequent)
(third-true-or-false-test third- onsequent)
...)
When the Lisp interpreter evaluates the ond expression, it evaluates the
rst element (the ar or true-or-false-test) of the rst expression in a series
of expressions within the body of the ond.
If the true-or-false-test returns nil the rest of that expression, the on-
sequent, is skipped and the true-or-false-test of the next expression is eval-
uated. When an expression is found whose true-or-false-test returns a value
that is not nil, the onsequent of that expression is evaluated. The onse-
quent an be one or more expressions. If the onsequent onsists of more
than one expression, the expressions are evaluated in sequen e and the value
of the last one is returned. If the expression does not have a onsequent, the
value of the true-or-false-test is returned.
If none of the true-or-false-tests test true, the ond expression returns
nil.
Written using ond, the triangle fun tion looks like this:
(defun triangle-using- ond (number)
( ond ((<= number 0) 0)
((= number 1) 1)
((> number 1)
(+ number (triangle-using- ond (1- number))))))
In this example, the ond returns 0 if the number is less than or equal to
0, it returns 1 if the number is 1 and it evaluates (+ number (triangle-
using- ond (1- number))) if the number is greater than 1.

11.3.6 Re ursive Patterns


Here are three ommon re ursive patterns. Ea h involves a list. Re ursion
does not need to involve lists, but Lisp is designed for lists and this provides
a sense of its primal apabilities.
Re ursive Pattern: every 141

Re ursive Pattern: every


In the every re ursive pattern, an a tion is performed on every element
of a list.
The basi pattern is:
 If a list be empty, return nil.
 Else, a t on the beginning of the list (the ar of the list)
through a re ursive all by the fun tion on the rest (the dr) of
the list,
and, optionally, ombine the a ted-on element, using ons, with
the results of a ting on the rest.

Here is example:
(defun square-ea h (numbers-list)
"Square ea h of a NUMBERS LIST, re ursively."
(if (not numbers-list) ; do-again-test
nil
( ons
(* ( ar numbers-list) ( ar numbers-list))
(square-ea h ( dr numbers-list))))) ; next-step-expression
(square-ea h '(1 2 3))
) (1 4 9)

If numbers-list is empty, do nothing. But if it has ontent, onstru t a list


ombining the square of the rst number in the list with the result of the
re ursive all.
(The example follows the pattern exa tly: nil is returned if the numbers'
list is empty. In pra ti e, you would write the onditional so it arries out
the a tion when the numbers' list is not empty.)
The print-elements-re ursively fun tion (see Se tion 11.3.3, \Re ur-
sion with a List", page 136) is another example of an every pattern, ex ept
in this ase, rather than bring the results together using ons, we print ea h
element of output.
The print-elements-re ursively fun tion looks like this:
(setq animals '(gazelle giraffe lion tiger))
142 Chapter 11: Loops and Re ursion

(defun print-elements-re ursively (list)


"Print ea h element of LIST on a line of its own.
Uses re ursion."
(if list ; do-again-test
(progn
(print ( ar list)) ; body
(print-elements-re ursively ; re ursive all
( dr list))))) ; next-step-expression

(print-elements-re ursively animals)


The pattern for print-elements-re ursively is:
 If the list be empty, do nothing.
 But if the list has at least one element,
a t on the beginning of the list (the ar of the list),
and make a re ursive all on the rest (the dr) of the list.

Re ursive Pattern: a umulate


Another re ursive pattern is alled the a umulate pattern. In the
a umulate re ursive pattern, an a tion is performed on every element of a
list and the result of that a tion is a umulated with the results of perform-
ing the a tion on the other elements.
This is very like the `every' pattern using ons, ex ept that ons is not
used, but some other ombiner.
The pattern is:
 If a list be empty, return zero or some other onstant.
 Else, a t on the beginning of the list (the ar of the list),
and ombine that a ted-on element, using + or some other ombin-
ing fun tion, with
a re ursive all by the fun tion on the rest (the dr) of the list.
Here is an example:
(defun add-elements (numbers-list)
"Add the elements of NUMBERS-LIST together."
(if (not numbers-list)
0
(+ ( ar numbers-list) (add-elements ( dr numbers-list)))))
(add-elements '(1 2 3 4))
) 10
See Se tion 14.9.2, \Making a List of Files", page 194, for an example of
the a umulate pattern.
Re ursion without Deferments 143

Re ursive Pattern: keep


A third re ursive pattern is alled the keep pattern. In the keep re ursive
pattern, ea h element of a list is tested; the element is a ted on and the
results are kept only if the element meets a riterion.
Again, this is very like the `every' pattern, ex ept the element is skipped
unless it meets a riterion.
The pattern has three parts:
 If a list be empty, return nil.
 Else, if the beginning of the list (the ar of the list) passes a test
a t on that element and ombine it, using ons with
a re ursive all by the fun tion on the rest (the dr) of the list.
 Otherwise, if the beginning of the list (the ar of the list) fails the test
skip on that element,
and, re ursively all the fun tion on the rest (the dr) of the list.
Here is an example that uses ond:
(defun keep-three-letter-words (word-list)
"Keep three letter words in WORD-LIST."
( ond
;; First do-again-test: stop- ondition
((not word-list) nil)

;; Se ond do-again-test: when to a t


((eq 3 (length (symbol-name ( ar word-list))))
;; ombine a ted-on element with re ursive all on shorter list
( ons ( ar word-list) (keep-three-letter-words ( dr word-list))))

;; Third do-again-test: when to skip element;


;; re ursively all shorter list with next-step expression
(t (keep-three-letter-words ( dr word-list)))))
(keep-three-letter-words '(one two three four five six))
) (one two six)
It goes without saying that you need not use nil as the test for when to
stop; and you an, of ourse, ombine these patterns.

11.3.7 Re ursion without Deferments


Let's onsider again what happens with the triangle-re ursively fun -
tion. We will nd that the intermediate al ulations are deferred until all
an be done.
144 Chapter 11: Loops and Re ursion

Here is the fun tion de nition:


(defun triangle-re ursively (number)
"Return the sum of the numbers 1 through NUMBER in lusive.
Uses re ursion."
(if (= number 1) ; do-again-test
1 ; then-part
(+ number ; else-part
(triangle-re ursively ; re ursive all
(1- number))))) ; next-step-expression
What happens when we all this fun tion with a argument of 7?
The rst instan e of the triangle-re ursively fun tion adds the num-
ber 7 to the value returned by a se ond instan e of triangle-re ursively,
an instan e that has been passed an argument of 6. That is to say, the rst
al ulation is:
(+ 7 (triangle-re ursively 6)
The rst instan e of triangle-re ursively|you may want to think of it
as a little robot| annot omplete its job. It must hand o the al ulation
for (triangle-re ursively 6) to a se ond instan e of the program, to a
se ond robot. This se ond individual is ompletely di erent from the rst
one; it is, in the jargon, a `di erent instantiation'. Or, put another way, it
is a di erent robot. It is the same model as the rst; it al ulates triangle
numbers re ursively; but it has a di erent serial number.
And what does (triangle-re ursively 6) return? It returns the num-
ber 6 added to the value returned by evaluating triangle-re ursively
with an argument of 5. Using the robot metaphor, it asks yet another robot
to help it.
Now the total is:
(+ 7 6 (triangle-re ursively 5)
And what happens next?
(+ 7 6 5 (triangle-re ursively 4)
Ea h time triangle-re ursively is alled, ex ept for the last time,
it reates another instan e of the program|another robot|and asks it to
make a al ulation.
Eventually, the full addition is set up and performed:
(+ 7 6 5 4 3 2 1)
This design for the fun tion defers the al ulation of the rst step until
the se ond an be done, and defers that until the third an be done, and
so on. Ea h deferment means the omputer must remember what is being
waited on. This is not a problem when there are only a few steps, as in this
example. But it an be a problem when there are more steps.
No Deferment Solution 145

11.3.8 No Deferment Solution


The solution to the problem of deferred operations is to write in a manner
that does not defer operations2. This requires writing to a di erent pattern,
often one that involves writing two fun tion de nitions, an `initialization'
fun tion and a `helper' fun tion.
The `initialization' fun tion sets up the job; the `helper' fun tion does the
work.
Here are the two fun tion de nitions for adding up numbers. They are
so simple, I nd them hard to understand.
(defun triangle-initialization (number)
"Return the sum of the numbers 1 through NUMBER in lusive.
This is the `initialization' omponent of a two fun tion
duo that uses re ursion."
(triangle-re ursive-helper 0 0 number))
(defun triangle-re ursive-helper (sum ounter number)
"Return SUM, using COUNTER, through NUMBER in lusive.
This is the `helper' omponent of a two fun tion duo
that uses re ursion."
(if (> ounter number)
sum
(triangle-re ursive-helper (+ sum ounter) ; sum
(1+ ounter) ; ounter
number))) ; number
Install both fun tion de nitions by evaluating them, then all triangle-
initialization with 2 rows:
(triangle-initialization 2)
) 3
The `initialization' fun tion alls the rst instan e of the `helper' fun tion
with three arguments: zero, zero, and a number whi h is the number of rows
in the triangle.
The rst two arguments passed to the `helper' fun tion are initializa-
tion values. These values are hanged when triangle-re ursive-helper
invokes new instan es.3
2 The phrase tail re ursive is used to des ribe su h a pro ess, one that uses ` onstant
spa e'.
3 The jargon is mildly onfusing: triangle-re ursive-helper uses a pro ess that is
iterative in a pro edure that is re ursive. The pro ess is alled iterative be ause the
omputer need only re ord the three values, sum, ounter, and number; the pro edure
is re ursive be ause the fun tion ` alls itself'. On the other hand, both the pro ess
and the pro edure used by triangle-re ursively are alled re ursive. The word
`re ursive' has di erent meanings in the two ontexts.
146 Chapter 11: Loops and Re ursion

Let's see what happens when we have a triangle that has one row. (This
triangle will have one pebble in it!)
triangle-initialization will all its helper with the arguments 0 0 1.
That fun tion will run the onditional test whether (> ounter number):
(> 0 1)
and nd that the result is false, so it will invoke the then-part of the if
lause:
(triangle-re ursive-helper
(+ sum ounter) ; sum plus ounter ) sum
(1+ ounter) ; in rement ounter ) ounter
number) ; number stays the same
whi h will rst ompute:
(triangle-re ursive-helper (+ 0 0) ; sum
(1+ 0) ; ounter
1) ; number
whi h is:
(triangle-re ursive-helper 0 1 1)
Again, (> ounter number) will be false, so again, the Lisp interpreter
will evaluate triangle-re ursive-helper, reating a new instan e with
new arguments.
This new instan e will be;
(triangle-re ursive-helper
(+ sum ounter) ; sum plus ounter ) sum
(1+ ounter) ; in rement ounter ) ounter
number) ; number stays the same

whi h is:
(triangle-re ursive-helper 1 2 1)
In this ase, the (> ounter number) test will be true! So the instan e
will return the value of the sum, whi h will be 1, as expe ted.
Now, let's pass triangle-initialization an argument of 2, to nd out
how many pebbles there are in a triangle with two rows.
That fun tion alls (triangle-re ursive-helper 0 0 2).
In stages, the instan es alled will be:
sum ounter number
(triangle-re ursive-helper 0 1 2)

(triangle-re ursive-helper 1 2 2)

(triangle-re ursive-helper 3 3 2)
Looping Exer ise 147

When the last instan e is alled, the (> ounter number) test will be
true, so the instan e will return the value of sum, whi h will be 3.
This kind of pattern helps when you are writing fun tions that an use
many resour es in a omputer.

11.4 Looping Exer ise


 Write a fun tion similar to triangle in whi h ea h row has a value
whi h is the square of the row number. Use a while loop.
 Write a fun tion similar to triangle that multiplies instead of adds the
values.
 Rewrite these two fun tions re ursively. Rewrite these fun tions using
ond.
 Write a fun tion for Texinfo mode that reates an index entry at the
beginning of a paragraph for every `dfn' within the paragraph. (In
a Texinfo le, `dfn' marks a de nition. For more information, see
\Indi ating De nitions, Commands, et ." in Texinfo, The GNU Do u-
mentation Format.)
148 Chapter 11: Loops and Re ursion
The Regular Expression for senten e-end 149

12 Regular Expression Sear hes


Regular expression sear hes are used extensively in GNU Ema s. The
two fun tions, forward-senten e and forward-paragraph, illustrate these
sear hes well. They use regular expressions to nd where to move point.
The phrase `regular expression' is often written as `regexp'.
Regular expression sear hes are des ribed in se tion \Regular Expression
Sear h" in The GNU Ema s Manual, as well as in se tion \Regular Expres-
sions" in The GNU Ema s Lisp Referen e Manual. In writing this hapter,
I am presuming that you have at least a mild a quaintan e with them. The
major point to remember is that regular expressions permit you to sear h
for patterns as well as for literal strings of hara ters. For example, the ode
in forward-senten e sear hes for the pattern of possible hara ters that
ould mark the end of a senten e, and moves point to that spot.
Before looking at the ode for the forward-senten e fun tion, it is worth
onsidering what the pattern that marks the end of a senten e must be.
The pattern is dis ussed in the next se tion; following that is a des rip-
tion of the regular expression sear h fun tion, re-sear h-forward. The
forward-senten e fun tion is des ribed in the se tion following. Finally,
the forward-paragraph fun tion is des ribed in the last se tion of this hap-
ter. forward-paragraph is a omplex fun tion that introdu es several new
features.

12.1 The Regular Expression for senten e-end


The symbol senten e-end is bound to the pattern that marks the end
of a senten e. What should this regular expression be?
Clearly, a senten e may be ended by a period, a question mark, or an
ex lamation mark. Indeed, only lauses that end with one of those three
hara ters should be onsidered the end of a senten e. This means that the
pattern should in lude the hara ter set:
[.?!℄
However, we do not want forward-senten e merely to jump to a period,
a question mark, or an ex lamation mark, be ause su h a hara ter might
be used in the middle of a senten e. A period, for example, is used after
abbreviations. So other information is needed.
A ording to onvention, you type two spa es after every senten e, but
only one spa e after a period, a question mark, or an ex lamation mark in the
body of a senten e. So a period, a question mark, or an ex lamation mark
followed by two spa es is a good indi ator of an end of senten e. However, in
a le, the two spa es may instead be a tab or the end of a line. This means
that the regular expression should in lude these three items as alternatives.
150 Chapter 12: Regular Expression Sear hes

This group of alternatives will look like this:


\\($\\| \\| \\)
^ ^^
TAB SPC
Here, `$' indi ates the end of the line, and I have pointed out where the tab
and two spa es are inserted in the expression. Both are inserted by putting
the a tual hara ters into the expression.
Two ba kslashes, `\\', are required before the parentheses and verti al
bars: the rst ba kslash quotes the following ba kslash in Ema s; and the
se ond indi ates that the following hara ter, the parenthesis or the verti al
bar, is spe ial.
Also, a senten e may be followed by one or more arriage returns, like
this:
[
℄*
Like tabs and spa es, a arriage return is inserted into a regular expression
by inserting it literally. The asterisk indi ates that the hRETi is repeated zero
or more times.
But a senten e end does not onsist only of a period, a question mark or an
ex lamation mark followed by appropriate spa e: a losing quotation mark
or a losing bra e of some kind may pre ede the spa e. Indeed more than
one su h mark or bra e may pre ede the spa e. These require a expression
that looks like this:
[℄\"')}℄*
In this expression, the rst `℄' is the rst hara ter in the expression; the
se ond hara ter is `"', whi h is pre eded by a `\' to tell Ema s the `"' is not
spe ial. The last three hara ters are `'', `)', and `}'.
All this suggests what the regular expression pattern for mat hing the
end of a senten e should be; and, indeed, if we evaluate senten e-end we
nd that it returns the following value:
senten e-end
) "[.?!℄[℄\"')}℄*\\($\\| \\| \\)[
℄*"

12.2 The re-sear h-forward Fun tion


The re-sear h-forward fun tion is very like the sear h-forward fun -
tion. (See Se tion 8.1.3, \The sear h-forward Fun tion", page 92.)
re-sear h-forward sear hes for a regular expression. If the sear h is
su essful, it leaves point immediately after the last hara ter in the target.
If the sear h is ba kwards, it leaves point just before the rst hara ter in
the target. You may tell re-sear h-forward to return t for true. (Moving
point is therefore a `side e e t'.)
forward-senten e 151

Like sear h-forward, the re-sear h-forward fun tion takes four argu-
ments:
1. The rst argument is the regular expression that the fun tion sear hes
for. The regular expression will be a string between quotations marks.
2. The optional se ond argument limits how far the fun tion will sear h;
it is a bound, whi h is spe i ed as a position in the bu er.
3. The optional third argument spe i es how the fun tion responds to
failure: nil as the third argument auses the fun tion to signal an error
(and print a message) when the sear h fails; any other value auses it
to return nil if the sear h fails and t if the sear h su eeds.
4. The optional fourth argument is the repeat ount. A negative repeat
ount auses re-sear h-forward to sear h ba kwards.
The template for re-sear h-forward looks like this:
(re-sear h-forward "regular-expression"
limit-of-sear h
what-to-do-if-sear h-fails
repeat- ount)
The se ond, third, and fourth arguments are optional. However, if you
want to pass a value to either or both of the last two arguments, you must also
pass a value to all the pre eding arguments. Otherwise, the Lisp interpreter
will mistake whi h argument you are passing the value to.
In the forward-senten e fun tion, the regular expression will be the
value of the variable senten e-end, namely:
"[.?!℄[℄\"')}℄*\\($\\| \\| \\)[
℄*"
The limit of the sear h will be the end of the paragraph (sin e a senten e
annot go beyond a paragraph). If the sear h fails, the fun tion will return
nil; and the repeat ount will be provided by the argument to the forward-
senten e fun tion.

12.3 forward-senten e
The ommand to move the ursor forward a senten e is a straightforward
illustration of how to use regular expression sear hes in Ema s Lisp. Indeed,
the fun tion looks longer and more ompli ated than it is; this is be ause the
fun tion is designed to go ba kwards as well as forwards; and, optionally, over
more than one senten e. The fun tion is usually bound to the key ommand
M-e.
152 Chapter 12: Regular Expression Sear hes

Here is the ode for forward-senten e:


(defun forward-senten e (&optional arg)
"Move forward to next senten e-end. With argument, repeat.
With negative argument, move ba kward repeatedly to senten e-beginning.
Senten e ends are identified by the value of senten e-end
treated as a regular expression. Also, every paragraph boundary
terminates senten es as well."
(intera tive "p")
(or arg (setq arg 1))
(while (< arg 0)
(let ((par-beg
(save-ex ursion (start-of-paragraph-text) (point))))
(if (re-sear h-ba kward
( on at senten e-end "[^ \t\n℄") par-beg t)
(goto- har (1- (mat h-end 0)))
(goto- har par-beg)))
(setq arg (1+ arg)))
(while (> arg 0)
(let ((par-end
(save-ex ursion (end-of-paragraph-text) (point))))
(if (re-sear h-forward senten e-end par-end t)
(skip- hars-ba kward " \t\n")
(goto- har par-end)))
(setq arg (1- arg))))
The fun tion looks long at rst sight and it is best to look at its skeleton
rst, and then its mus le. The way to see the skeleton is to look at the
expressions that start in the left-most olumns:
(defun forward-senten e (&optional arg)
"do umentation..."
(intera tive "p")
(or arg (setq arg 1))
(while (< arg 0)
body-of-while-loop
(while (> arg 0)
body-of-while-loop
This looks mu h simpler! The fun tion de nition onsists of do umenta-
tion, an intera tive expression, an or expression, and while loops.
Let's look at ea h of these parts in turn.
We note that the do umentation is thorough and understandable.
The fun tion has an intera tive "p" de laration. This means that the
pro essed pre x argument, if any, is passed to the fun tion as its argument.
(This will be a number.) If the fun tion is not passed an argument (it
is optional) then the argument arg will be bound to 1. When forward-
The while loops 153

senten e is alled non-intera tively without an argument, arg is bound to


nil.
The or expression handles the pre x argument. What it does is either
leave the value of arg as it is, but only if arg is bound to a value; or it sets
the value of arg to 1, in the ase when arg is bound to nil.

The while loops


Two while loops follow the or expression. The rst while has a true-
or-false-test that tests true if the pre x argument for forward-senten e is
a negative number. This is for going ba kwards. The body of this loop is
similar to the body of the se ond while lause, but it is not exa tly the
same. We will skip this while loop and on entrate on the se ond while
loop.
The se ond while loop is for moving point forward. Its skeleton looks
like this:
(while (> arg 0) ; true-or-false-test
(let varlist
(if (true-or-false-test)
then-part
else-part
(setq arg (1- arg)))) ; while loop de rementer
The while loop is of the de rementing kind. (See Se tion 11.1.4, \A Loop
with a De rementing Counter", page 129.) It has a true-or-false-test that
tests true so long as the ounter (in this ase, the variable arg) is greater
than zero; and it has a de rementer that subtra ts 1 from the value of the
ounter every time the loop repeats.
If no pre x argument is given to forward-senten e, whi h is the most
ommon way the ommand is used, this while loop will run on e, sin e the
value of arg will be 1.
The body of the while loop onsists of a let expression, whi h reates
and binds a lo al variable, and has, as its body, an if expression.
The body of the while loop looks like this:
(let ((par-end
(save-ex ursion (end-of-paragraph-text) (point))))
(if (re-sear h-forward senten e-end par-end t)
(skip- hars-ba kward " \t\n")
(goto- har par-end)))
The let expression reates and binds the lo al variable par-end. As we
shall see, this lo al variable is designed to provide a bound or limit to the
regular expression sear h. If the sear h fails to nd a proper senten e ending
in the paragraph, it will stop on rea hing the end of the paragraph.
154 Chapter 12: Regular Expression Sear hes

But rst, let us examine how par-end is bound to the value of the end
of the paragraph. What happens is that the let sets the value of par-end
to the value returned when the Lisp interpreter evaluates the expression
(save-ex ursion (end-of-paragraph-text) (point))
In this expression, (end-of-paragraph-text) moves point to the end of the
paragraph, (point) returns the value of point, and then save-ex ursion
restores point to its original position. Thus, the let binds par-end to the
value returned by the save-ex ursion expression, whi h is the position of
the end of the paragraph. (The (end-of-paragraph-text) fun tion uses
forward-paragraph, whi h we will dis uss shortly.)
Ema s next evaluates the body of the let, whi h is an if expression that
looks like this:
(if (re-sear h-forward senten e-end par-end t) ; if-part
(skip- hars-ba kward " \t\n") ; then-part
(goto- har par-end))) ; else-part
The if tests whether its rst argument is true and if so, evaluates its
then-part; otherwise, the Ema s Lisp interpreter evaluates the else-part.
The true-or-false-test of the if expression is the regular expression sear h.
It may seem odd to have what looks like the `real work' of the forward-
senten e fun tion buried here, but this is a ommon way this kind of oper-
ation is arried out in Lisp.
The regular expression sear h
The re-sear h-forward fun tion sear hes for the end of the senten e,
that is, for the pattern de ned by the senten e-end regular expression.
If the pattern is found|if the end of the senten e is found|then the re-
sear h-forward fun tion does two things:
1. The re-sear h-forward fun tion arries out a side e e t, whi h is to
move point to the end of the o urren e found.
2. The re-sear h-forward fun tion returns a value of true. This is the
value re eived by the if, and means that the sear h was su essful.
The side e e t, the movement of point, is ompleted before the if fun tion
is handed the value returned by the su essful on lusion of the sear h.
When the if fun tion re eives the value of true from a su essful all to
re-sear h-forward, the if evaluates the then-part, whi h is the expression
(skip- hars-ba kward " \t\n"). This expression moves ba kwards over
any blank spa es, tabs or arriage returns until a printed hara ter is found
and then leaves point after the hara ter. Sin e point has already been
moved to the end of the pattern that marks the end of the senten e, this
a tion leaves point right after the losing printed hara ter of the senten e,
whi h is usually a period.
On the other hand, if the re-sear h-forward fun tion fails to nd a
pattern marking the end of the senten e, the fun tion returns false. The
forward-paragraph: a Goldmine of Fun tions 155

false then auses the if to evaluate its third argument, whi h is (goto- har
par-end): it moves point to the end of the paragraph.
Regular expression sear hes are ex eptionally useful and the pattern il-
lustrated by re-sear h-forward, in whi h the sear h is the test of an if
expression, is handy. You will see or write ode in orporating this pattern
often.

12.4 forward-paragraph: a Goldmine of Fun tions


The forward-paragraph fun tion moves point forward to the end of the
paragraph. It is usually bound to M-} and makes use of a number of fun tions
that are important in themselves, in luding let*, mat h-beginning, and
looking-at.
The fun tion de nition for forward-paragraph is onsiderably longer
than the fun tion de nition for forward-senten e be ause it works with a
paragraph, ea h line of whi h may begin with a ll pre x.
A ll pre x onsists of a string of hara ters that are repeated at the
beginning of ea h line. For example, in Lisp ode, it is a onvention to start
ea h line of a paragraph-long omment with `;;; '. In Text mode, four blank
spa es make up another ommon ll pre x, reating an indented paragraph.
(See se tion \Fill Pre x" in The GNU Ema s Manual, for more information
about ll pre xes.)
The existen e of a ll pre x means that in addition to being able to
nd the end of a paragraph whose lines begin on the left-most olumn, the
forward-paragraph fun tion must be able to nd the end of a paragraph
when all or many of the lines in the bu er begin with the ll pre x.
Moreover, it is sometimes pra ti al to ignore a ll pre x that exists, espe-
ially when blank lines separate paragraphs. This is an added ompli ation.
Rather than print all of the forward-paragraph fun tion, we will only
print parts of it. Read without preparation, the fun tion an be daunting!
In outline, the fun tion looks like this:
(defun forward-paragraph (&optional arg)
"do umentation..."
(intera tive "p")
(or arg (setq arg 1))
(let*
varlist
(while (< arg 0) ; ba kward-moving- ode
...
(setq arg (1+ arg)))
(while (> arg 0) ; forward-moving- ode
...
(setq arg (1- arg)))))
156 Chapter 12: Regular Expression Sear hes

The rst parts of the fun tion are routine: the fun tion's argument list
onsists of one optional argument. Do umentation follows.
The lower ase `p' in the intera tive de laration means that the pro-
essed pre x argument, if any, is passed to the fun tion. This will be a
number, and is the repeat ount of how many paragraphs point will move.
The or expression in the next line handles the ommon ase when no argu-
ment is passed to the fun tion, whi h o urs if the fun tion is alled from
other ode rather than intera tively. This ase was des ribed earlier. (See
Se tion 12.3, \forward-senten e", page 151.) Now we rea h the end of the
familiar part of this fun tion.

The let* expression


The next line of the forward-paragraph fun tion begins a let* expres-
sion. This is a di erent kind of expression than we have seen so far. The
symbol is let* not let.
The let* spe ial form is like let ex ept that Ema s sets ea h variable
in sequen e, one after another, and variables in the latter part of the varlist
an make use of the values to whi h Ema s set variables in the earlier part
of the varlist.
In the let* expression in this fun tion, Ema s binds two variables: fill-
prefix-regexp and paragraph-separate. The value to whi h paragraph-
separate is bound depends on the value of fill-prefix-regexp.
Let's look at ea h in turn. The symbol fill-prefix-regexp is set to
the value returned by evaluating the following list:
(and fill-prefix
(not (equal fill-prefix ""))
(not paragraph-ignore-fill-prefix)
(regexp-quote fill-prefix))
This is an expression whose rst element is the and spe ial form.
As we learned earlier (see \The kill-new fun tion", page 105), the and
spe ial form evaluates ea h of its arguments until one of the arguments
returns a value of nil, in whi h ase the and expression returns nil; however,
if none of the arguments returns a value of nil, the value resulting from
evaluating the last argument is returned. (Sin e su h a value is not nil, it
is onsidered true in Lisp.) In other words, an and expression returns a true
value only if all its arguments are true.
In this ase, the variable fill-prefix-regexp is bound to a non-nil
value only if the following four expressions produ e a true (i.e., a non-nil)
value when they are evaluated; otherwise, fill-prefix-regexp is bound to
nil.
The let* expression 157

fill-prefix
When this variable is evaluated, the value of the ll pre x, if
any, is returned. If there is no ll pre x, this variable returns
nil.
(not (equal fill-prefix "")
This expression he ks whether an existing ll pre x is an empty
string, that is, a string with no hara ters in it. An empty string
is not a useful ll pre x.
(not paragraph-ignore-fill-prefix)
This expression returns nil if the variable paragraph-ignore-
fill-prefix has been turned on by being set to a true value
su h as t.
(regexp-quote fill-prefix)
This is the last argument to the and spe ial form. If all the
arguments to the and are true, the value resulting from evaluat-
ing this expression will be returned by the and expression and
bound to the variable fill-prefix-regexp,
The result of evaluating this and expression su essfully is that fill-
prefix-regexp will be bound to the value of fill-prefix as modi ed by
the regexp-quote fun tion. What regexp-quote does is read a string and
return a regular expression that will exa tly mat h the string and mat h
nothing else. This means that fill-prefix-regexp will be set to a value
that will exa tly mat h the ll pre x if the ll pre x exists. Otherwise, the
variable will be set to nil.
The se ond lo al variable in the let* expression is paragraph-separate.
It is bound to the value returned by evaluating the expression:
(if fill-prefix-regexp
( on at paragraph-separate
"\\|^" fill-prefix-regexp "[ \t℄*$")
paragraph-separate)))
This expression shows why let* rather than let was used. The true-or-
false-test for the if depends on whether the variable fill-prefix-regexp
evaluates to nil or some other value.
If fill-prefix-regexp does not have a value, Ema s evaluates the else-
part of the if expression and binds paragraph-separate to its lo al value.
(paragraph-separate is a regular expression that mat hes what separates
paragraphs.)
But if fill-prefix-regexp does have a value, Ema s evaluates the then-
part of the if expression and binds paragraph-separate to a regular ex-
pression that in ludes the fill-prefix-regexp as part of the pattern.
Spe i ally, paragraph-separate is set to the original value of the para-
graph separate regular expression on atenated with an alternative expres-
sion that onsists of the fill-prefix-regexp followed by a blank line. The
158 Chapter 12: Regular Expression Sear hes

`^' indi ates that the fill-prefix-regexp must begin a line, and the op-
tional whitespa e to the end of the line is de ned by "[ \t℄*$".) The `\\|'
de nes this portion of the regexp as an alternative to paragraph-separate.
Now we get into the body of the let*. The rst part of the body of the
let* deals with the ase when the fun tion is given a negative argument and
is therefore moving ba kwards. We will skip this se tion.

The forward motion while loop


The se ond part of the body of the let* deals with forward motion. It
is a while loop that repeats itself so long as the value of arg is greater than
zero. In the most ommon use of the fun tion, the value of the argument is
1, so the body of the while loop is evaluated exa tly on e, and the ursor
moves forward one paragraph.
This part handles three situations: when point is between paragraphs,
when point is within a paragraph and there is a ll pre x, and when point
is within a paragraph and there is no ll pre x.
The while loop looks like this:
(while (> arg 0)
(beginning-of-line)

;; between paragraphs
(while (prog1 (and (not (eobp))
(looking-at paragraph-separate))
(forward-line 1)))
;; within paragraphs, with a ll pre x
(if fill-prefix-regexp
;; There is a ll pre x; it overrides paragraph-start.
(while (and (not (eobp))
(not (looking-at paragraph-separate))
(looking-at fill-prefix-regexp))
(forward-line 1))
;; within paragraphs, no ll pre x
(if (re-sear h-forward paragraph-start nil t)
(goto- har (mat h-beginning 0))
(goto- har (point-max))))

(setq arg (1- arg)))

We an see immediately that this is a de rementing ounter while loop,


using the expression (setq arg (1- arg)) as the de rementer.
Between paragraphs 159

The body of the loop onsists of three expressions:


;; between paragraphs
(beginning-of-line)
(while
body-of-while )
;; within paragraphs, with ll pre x
(if true-or-false-test
then-part
;; within paragraphs, no ll pre x
else-part
When the Ema s Lisp interpreter evaluates the body of the while loop, the
rst thing it does is evaluate the (beginning-of-line) expression and move
point to the beginning of the line. Then there is an inner while loop. This
while loop is designed to move the ursor out of the blank spa e between
paragraphs, if it should happen to be there. Finally, there is an if expression
that a tually moves point to the end of the paragraph.

Between paragraphs
First, let us look at the inner while loop. This loop handles the ase
when point is between paragraphs; it uses three fun tions that are new to
us: prog1, eobp and looking-at.
 prog1 is similar to the progn spe ial form, ex ept that prog1 evaluates
its arguments in sequen e and then returns the value of its rst argument
as the value of the whole expression. (progn returns the value of its last
argument as the value of the expression.) The se ond and subsequent
arguments to prog1 are evaluated only for their side e e ts.
 eobp is an abbreviation of `End Of Buffer P' and is a fun tion that
returns true if point is at the end of the bu er.
 looking-at is a fun tion that returns true if the text following point
mat hes the regular expression passed looking-at as its argument.
The while loop we are studying looks like this:
(while (prog1 (and (not (eobp))
(looking-at paragraph-separate))
(forward-line 1)))
This is a while loop with no body! The true-or-false-test of the loop is the
expression:
(prog1 (and (not (eobp))
(looking-at paragraph-separate))
(forward-line 1))
The rst argument to the prog1 is the and expression. It has within in it a
test of whether point is at the end of the bu er and also a test of whether
160 Chapter 12: Regular Expression Sear hes

the pattern following point mat hes the regular expression for separating
paragraphs.
If the ursor is not at the end of the bu er and if the hara ters fol-
lowing the ursor mark the separation between two paragraphs, then the
and expression is true. After evaluating the and expression, the Lisp inter-
preter evaluates the se ond argument to prog1, whi h is forward-line. This
moves point forward one line. The value returned by the prog1 however, is
the value of its rst argument, so the while loop ontinues so long as point
is not at the end of the bu er and is between paragraphs. When, nally,
point is moved to a paragraph, the and expression tests false. Note however,
that the forward-line ommand is arried out anyhow. This means that
when point is moved from between paragraphs to a paragraph, it is left at
the beginning of the se ond line of the paragraph.

Within paragraphs
The next expression in the outer while loop is an if expression. The
Lisp interpreter evaluates the then-part of the if when the fill-prefix-
regexp variable has a value other than nil, and it evaluates the else-part
when the value of if fill-prefix-regexp is nil, that is, when there is no
ll pre x.

No ll pre x
It is simplest to look at the ode for the ase when there is no ll pre x
rst. This ode onsists of yet another inner if expression, and reads as
follows:
(if (re-sear h-forward paragraph-start nil t)
(goto- har (mat h-beginning 0))
(goto- har (point-max)))
This expression a tually does the work that most people think of as the
primary purpose of the forward-paragraph ommand: it auses a regular
expression sear h to o ur that sear hes forward to the start of the next
paragraph and if it is found, moves point there; but if the start of another
paragraph if not found, it moves point to the end of the a essible region of
the bu er.
The only unfamiliar part of this is the use of mat h-beginning. This is
another fun tion that is new to us. The mat h-beginning fun tion returns
a number spe ifying the lo ation of the start of the text that was mat hed
by the last regular expression sear h.
The mat h-beginning fun tion is used here be ause of a hara teristi
of a forward sear h: a su essful forward sear h, regardless of whether it is
a plain sear h or a regular expression sear h, will move point to the end of
the text that is found. In this ase, a su essful sear h will move point to
Summary 161

the end of the pattern for paragraph-start, whi h will be the beginning of
the next paragraph rather than the end of the urrent one.
However, we want to put point at the end of the urrent paragraph, not at
the beginning of the next one. The two positions may be di erent, be ause
there may be several blank lines between paragraphs.
When given an argument of 0, mat h-beginning returns the position
that is the start of the text that the most re ent regular expression sear h
mat hed. In this ase, the most re ent regular expression sear h is the one
looking for paragraph-start, so mat h-beginning returns the beginning
position of the pattern, rather than the end of the pattern. The beginning
position is the end of the paragraph.
(In identally, when passed a positive number as an argument, the mat h-
beginning fun tion will pla e point at that parenthesized expression in the
last regular expression. It is a useful fun tion.)

With a ll pre x
The inner if expression just dis ussed is the else-part of an en losing if
expression whi h tests whether there is a ll pre x. If there is a ll pre x,
the then-part of this if is evaluated. It looks like this:
(while (and (not (eobp))
(not (looking-at paragraph-separate))
(looking-at fill-prefix-regexp))
(forward-line 1))
What this expression does is move point forward line by line so long as three
onditions are true:
1. Point is not at the end of the bu er.
2. The text following point does not separate paragraphs.
3. The pattern following point is the ll pre x regular expression.
The last ondition may be puzzling, until you remember that point was
moved to the beginning of the line early in the forward-paragraph fun tion.
This means that if the text has a ll pre x, the looking-at fun tion will
see it.

Summary
In summary, when moving forward, the forward-paragraph fun tion
does the following:
 Move point to the beginning of the line.
 Skip over lines between paragraphs.
 Che k whether there is a ll pre x, and if there is:
| Go forward line by line so long as the line is not a paragraph sep-
arating line.
162 Chapter 12: Regular Expression Sear hes

 But if there is no ll pre x,


| Sear h for the next paragraph start pattern.
| Go to the beginning of the paragraph start pattern, whi h will be
the end of the previous paragraph.
| Or else go to the end of the a essible portion of the bu er.
For review, here is the ode we have just been dis ussing, formatted for
larity:
(intera tive "p")
(or arg (setq arg 1))
(let* (
(fill-prefix-regexp
(and fill-prefix (not (equal fill-prefix ""))
(not paragraph-ignore-fill-prefix)
(regexp-quote fill-prefix)))
(paragraph-separate
(if fill-prefix-regexp
( on at paragraph-separate
"\\|^"
fill-prefix-regexp
"[ \t℄*$")
paragraph-separate)))

omitted-ba kward-moving- ode ...


(while (> arg 0) ; forward-moving- ode
(beginning-of-line)

(while (prog1 (and (not (eobp))


(looking-at paragraph-separate))
(forward-line 1)))
(if fill-prefix-regexp
(while (and (not (eobp)) ; then-part
(not (looking-at paragraph-separate))
(looking-at fill-prefix-regexp))
(forward-line 1))
; else-part: the inner-if
(if (re-sear h-forward paragraph-start nil t)
(goto- har (mat h-beginning 0))
(goto- har (point-max))))

(setq arg (1- arg))))) ; de rementer


The full de nition for the forward-paragraph fun tion not only in ludes
this ode for going forwards, but also ode for going ba kwards.
Create Your Own `TAGS' File 163

If you are reading this inside of GNU Ema s and you want to see the
whole fun tion, you an type C-h f (des ribe-fun tion) and the name of
the fun tion. This gives you the fun tion do umentation and the name of
the library ontaining the fun tion's sour e. Pla e point over the name of
the library and press the RET key; you will be taken dire tly to the sour e.
(Be sure to install your sour es! Without them, you are like a person who
tries to drive a ar with his eyes shut!)
Or { a good habit to get into { you an type M-. (find-tag) and
the name of the fun tion when prompted for it. This will take you di-
re tly to the sour e. If the find-tag fun tion rst asks you for the
name of a `TAGS' table, give it the name of the `TAGS' le su h as
`/usr/lo al/share/ema s/21.0.100/lisp/TAGS'. (The exa t path to your
`TAGS' le depends on how your opy of Ema s was installed.)
You an also reate your own `TAGS' le for dire tories that la k one.

12.5 Create Your Own `TAGS' File


The M-. (find-tag) ommand takes you dire tly to the sour e for a
fun tion, variable, node, or other sour e. The fun tion depends on tags
tables to tell it where to go.
You often need to build and install tags tables yourself. They are not
built automati ally. A tags table is alled a `TAGS' le; the name is in upper
ase letters.
You an reate a `TAGS' le by alling the etags program that omes as
a part of the Ema s distribution. Usually, etags is ompiled and installed
when Ema s is built. (etags is not an Ema s Lisp fun tion or a part of
Ema s; it is a C program.)
To reate a `TAGS' le, rst swit h to the dire tory in whi h you want
to reate the le. In Ema s you an do this with the M-x d ommand,
or by visiting a le in the dire tory, or by listing the dire tory with C-x d
(dired). Then run the ompile ommand, with etags *.el as the ommand
to exe ute
M-x ompile RET etags *.el RET
to reate a `TAGS' le.
For example, if you have a large number of les in your `~/ema s' dire -
tory, as I do|I have 137 `.el' les in it, of whi h I load 12|you an reate
a `TAGS' le for the Ema s Lisp les in that dire tory.
The etags program takes all the usual shell `wild ards'. For example,
if you have two dire tories for whi h you want a single `TAGS file', type
etags *.el ../elisp/*.el, where `../elisp/' is the se ond dire tory:
M-x ompile RET etags *.el ../elisp/*.el RET
164 Chapter 12: Regular Expression Sear hes

Type
M-x ompile RET etags --help RET
to see a list of the options a epted by etags as well as a list of supported
languages.
The etags program handles more than 20 languages, in luding Ema s
Lisp, Common Lisp, S heme, C, C++, Ada, Fortran, Java, LaTeX, Pas al,
Perl, Python, Texinfo, make les, and most assemblers. The program has no
swit hes for spe ifying the language; it re ognizes the language in an input
le a ording to its le name and ontents.
`etags' is very helpful when you are writing ode yourself and want to
refer ba k to fun tions you have already written. Just run etags again at
intervals as you write new fun tions, so they be ome part of the `TAGS' le.
If you think an appropriate `TAGS' le already exists for what you want,
but do not know where it is, you an use the lo ate program to attempt to
nd it.
Type M-x lo ate RET TAGS RET and Ema s will list for you the full path
names of all your `TAGS' les. On my system, this ommand lists 34 `TAGS'
les. On the other hand, a `plain vanilla' system I re ently installed did not
ontain any `TAGS' les.
If the tags table you want has been reated, you an use the M-x visit-
tags-table ommand to spe ify it. Otherwise, you will need to reate the
tag table yourself and then use M-x visit-tags-table.

Building Tags in the Ema s sour es


The GNU Ema s sour es ome with a `Makefile' that ontains a sophis-
ti ated etags ommand that reates, olle ts, and merges tags tables from
all over the Ema s sour es and puts the information into one `TAGS' le in
the `sr /' dire tory below the top level of your Ema s sour e dire tory.
To build this `TAGS' le, go to the top level of your Ema s sour e dire tory
and run the ompile ommand make tags:
M-x ompile RET make tags RET
(The make tags ommand works well with the GNU Ema s sour es, as well
as with some other sour e pa kages.)
For more information, see se tion \Tag Tables" in The GNU Ema s Man-
ual.

12.6 Review
Here is a brief summary of some re ently introdu ed fun tions.
while Repeatedly evaluate the body of the expression so long as the
rst element of the body tests true. Then return nil. (The
expression is evaluated only for its side e e ts.)
Review 165

For example:
(let ((foo 2))
(while (> foo 0)
(insert (format "foo is %d.\n" foo))
(setq foo (1- foo))))

) foo is 2.
foo is 1.
nil
(The insert fun tion inserts its arguments at point; the format
fun tion returns a string formatted from its arguments the way
message formats its arguments; \n produ es a new line.)
re-sear h-forward
Sear h for a pattern, and if the pattern is found, move point to
rest just after it.
Takes four arguments, like sear h-forward:
1. A regular expression that spe i es the pattern to sear h for.
2. Optionally, the limit of the sear h.
3. Optionally, what to do if the sear h fails, return nil or an
error message.
4. Optionally, how many times to repeat the sear h; if nega-
tive, the sear h goes ba kwards.
let* Bind some variables lo ally to parti ular values, and then eval-
uate the remaining arguments, returning the value of the last
one. While binding the lo al variables, use the lo al values of
variables bound earlier, if any.
For example:
(let* ((foo 7)
(bar (* 3 foo)))
(message "`bar' is %d." bar))
) `bar' is 21.
mat h-beginning
Return the position of the start of the text found by the last
regular expression sear h.
looking-at
Return t for true if the text after point mat hes the argument,
whi h should be a regular expression.
eobp Return t for true if point is at the end of the a essible part of
a bu er. The end of the a essible part is the end of the bu er
if the bu er is not narrowed; it is the end of the narrowed part
if the bu er is narrowed.
166 Chapter 12: Regular Expression Sear hes

prog1 Evaluate ea h argument in sequen e and then return the value


of the rst.
For example:
(prog1 1 2 3 4)
) 1

12.7 Exer ises with re-sear h-forward


 Write a fun tion to sear h for a regular expression that mat hes two or
more blank lines in sequen e.
 Write a fun tion to sear h for dupli ated words, su h as `the the'. See
se tion \Syntax of Regular Expressions" in The GNU Ema s Manual,
for information on how to write a regexp (a regular expression) to mat h
a string that is omposed of two identi al halves. You an devise several
regexps; some are better than others. The fun tion I use is des ribed
in an appendix, along with several regexps. See Appendix A, \the-the
Dupli ated Words Fun tion", page 241.
The ount-words-region Fun tion 167

13 Counting: Repetition and Regexps


Repetition and regular expression sear hes are powerful tools that you
often use when you write ode in Ema s Lisp. This hapter illustrates the
use of regular expression sear hes through the onstru tion of word ount
ommands using while loops and re ursion.
The standard Ema s distribution ontains a fun tion for ounting the
number of lines within a region. However, there is no orresponding fun tion
for ounting words.
Certain types of writing ask you to ount words. Thus, if you write
an essay, you may be limited to 800 words; if you write a novel, you may
dis ipline yourself to write 1000 words a day. It seems odd to me that
Ema s la ks a word ount ommand. Perhaps people use Ema s mostly for
ode or types of do umentation that do not require word ounts; or perhaps
they restri t themselves to the operating system word ount ommand, w .
Alternatively, people may follow the publishers' onvention and ompute a
word ount by dividing the number of hara ters in a do ument by ve. In
any event, here are ommands to ount words.

13.1 The ount-words-region Fun tion


A word ount ommand ould ount words in a line, paragraph, region,
or bu er. What should the ommand over? You ould design the ommand
to ount the number of words in a omplete bu er. However, the Ema s tra-
dition en ourages exibility|you may want to ount words in just a se tion,
rather than all of a bu er. So it makes more sense to design the ommand
to ount the number of words in a region. On e you have a ount-words-
region ommand, you an, if you wish, ount words in a whole bu er by
marking it with C-x h (mark-whole-buffer).
Clearly, ounting words is a repetitive a t: starting from the beginning
of the region, you ount the rst word, then the se ond word, then the third
word, and so on, until you rea h the end of the region. This means that
word ounting is ideally suited to re ursion or to a while loop.
First, we will implement the word ount ommand with a while loop,
then with re ursion. The ommand will, of ourse, be intera tive.
The template for an intera tive fun tion de nition is, as always:
(defun name-of-fun tion (argument-list)
"do umentation..."
(intera tive-expression...)
body ...)
What we need to do is ll in the slots.
The name of the fun tion should be self-explanatory and similar to the
existing ount-lines-region name. This makes the name easier to remem-
ber. ount-words-region is a good hoi e.
168 Chapter 13: Counting: Repetition and Regexps

The fun tion ounts words within a region. This means that the argument
list must ontain symbols that are bound to the two positions, the beginning
and end of the region. These two positions an be alled `beginning' and
`end' respe tively. The rst line of the do umentation should be a single sen-
ten e, sin e that is all that is printed as do umentation by a ommand su h
as apropos. The intera tive expression will be of the form `(intera tive
"r")', sin e that will ause Ema s to pass the beginning and end of the
region to the fun tion's argument list. All this is routine.
The body of the fun tion needs to be written to do three tasks: rst, to
set up onditions under whi h the while loop an ount words, se ond, to
run the while loop, and third, to send a message to the user.
When a user alls ount-words-region, point may be at the beginning
or the end of the region. However, the ounting pro ess must start at the
beginning of the region. This means we will want to put point there if
it is not already there. Exe uting (goto- har beginning) ensures this.
Of ourse, we will want to return point to its expe ted position when the
fun tion nishes its work. For this reason, the body must be en losed in a
save-ex ursion expression.
The entral part of the body of the fun tion onsists of a while loop
in whi h one expression jumps point forward word by word, and another
expression ounts those jumps. The true-or-false-test of the while loop
should test true so long as point should jump forward, and false when point
is at the end of the region.
We ould use (forward-word 1) as the expression for moving point for-
ward word by word, but it is easier to see what Ema s identi es as a `word'
if we use a regular expression sear h.
A regular expression sear h that nds the pattern for whi h it is sear hing
leaves point after the last hara ter mat hed. This means that a su ession
of su essful word sear hes will move point forward word by word.
As a pra ti al matter, we want the regular expression sear h to jump
over whitespa e and pun tuation between words as well as over the words
themselves. A regexp that refuses to jump over interword whitespa e would
never jump more than one word! This means that the regexp should in lude
the whitespa e and pun tuation that follows a word, if any, as well as the
word itself. (A word may end a bu er and not have any following whitespa e
or pun tuation, so that part of the regexp must be optional.)
Thus, what we want for the regexp is a pattern de ning one or more word
onstituent hara ters followed, optionally, by one or more hara ters that
are not word onstituents. The regular expression for this is:
\w+\W*
The bu er's syntax table determines whi h hara ters are and are not word
onstituents. (See Se tion 14.2, \What Constitutes a Word or Symbol?",
page 182, for more about syntax. Also, see se tion \The Syntax Table" in
The ount-words-region Fun tion 169

The GNU Ema s Manual, and se tion \Syntax Tables" in The GNU Ema s
Lisp Referen e Manual.)
The sear h expression looks like this:
(re-sear h-forward "\\w+\\W*")
(Note that paired ba kslashes pre ede the `w' and `W'. A single ba kslash
has spe ial meaning to the Ema s Lisp interpreter. It indi ates that the fol-
lowing hara ter is interpreted di erently than usual. For example, the two
hara ters, `\n', stand for `newline', rather than for a ba kslash followed by
`n'. Two ba kslashes in a row stand for an ordinary, `unspe ial' ba kslash.)
We need a ounter to ount how many words there are; this variable
must rst be set to 0 and then in remented ea h time Ema s goes around
the while loop. The in rementing expression is simply:
(setq ount (1+ ount))
Finally, we want to tell the user how many words there are in the region.
The message fun tion is intended for presenting this kind of information to
the user. The message has to be phrased so that it reads properly regardless
of how many words there are in the region: we don't want to say that \there
are 1 words in the region". The on i t between singular and plural is
ungrammati al. We an solve this problem by using a onditional expression
that evaluates di erent messages depending on the number of words in the
region. There are three possibilities: no words in the region, one word in the
region, and more than one word. This means that the ond spe ial form is
appropriate.
All this leads to the following fun tion de nition:
;;; First version; has bugs!
(defun ount-words-region (beginning end)
"Print number of words in the region.
Words are defined as at least one word- onstituent
hara ter followed by at least one hara ter that
is not a word- onstituent. The buffer's syntax
table determines whi h hara ters these are."
(intera tive "r")
(message "Counting words in region ... ")
;;; 1. Set up appropriate onditions.
(save-ex ursion
(goto- har beginning)
(let (( ount 0))
;;; 2. Run the while loop.
(while (< (point) end)
(re-sear h-forward "\\w+\\W*")
(setq ount (1+ ount)))
170 Chapter 13: Counting: Repetition and Regexps

;;; 3. Send a message to the user.


( ond ((zerop ount)
(message
"The region does NOT have any words."))
((= 1 ount)
(message
"The region has 1 word."))
(t
(message
"The region has %d words." ount))))))
As written, the fun tion works, but not in all ir umstan es.

13.1.1 The Whitespa e Bug in ount-words-region


The ount-words-region ommand des ribed in the pre eding se tion
has two bugs, or rather, one bug with two manifestations. First, if you
mark a region ontaining only whitespa e in the middle of some text, the
ount-words-region ommand tells you that the region ontains one word!
Se ond, if you mark a region ontaining only whitespa e at the end of the
bu er or the a essible portion of a narrowed bu er, the ommand displays
an error message that looks like this:
Sear h failed: "\\w+\\W*"
If you are reading this in Info in GNU Ema s, you an test for these bugs
yourself.
First, evaluate the fun tion in the usual manner to install it.
If you wish, you an also install this keybinding by evaluating it:
(global-set-key "\C- =" ' ount-words-region)
To ondu t the rst test, set mark and point to the beginning and end of
the following line and then type C- = (or M-x ount-words-region if you
have not bound C- =):
one two three
Ema s will tell you, orre tly, that the region has three words.
Repeat the test, but pla e mark at the beginning of the line and pla e
point just before the word `one'. Again type the ommand C- = (or M-x
ount-words-region). Ema s should tell you that the region has no words,
sin e it is omposed only of the whitespa e at the beginning of the line. But
instead Ema s tells you that the region has one word!
For the third test, opy the sample line to the end of the `*s rat h*'
bu er and then type several spa es at the end of the line. Pla e mark right
after the word `three' and point at the end of line. (The end of the line
will be the end of the bu er.) Type C- = (or M-x ount-words-region) as
you did before. Again, Ema s should tell you that the region has no words,
The Whitespa e Bug in ount-words-region 171

sin e it is omposed only of the whitespa e at the end of the line. Instead,
Ema s displays an error message saying `Sear h failed'.
The two bugs stem from the same problem.
Consider the rst manifestation of the bug, in whi h the ommand tells
you that the whitespa e at the beginning of the line ontains one word.
What happens is this: The M-x ount-words-region ommand moves point
to the beginning of the region. The while tests whether the value of point
is smaller than the value of end, whi h it is. Consequently, the regular
expression sear h looks for and nds the rst word. It leaves point after the
word. ount is set to one. The while loop repeats; but this time the value
of point is larger than the value of end, the loop is exited; and the fun tion
displays a message saying the number of words in the region is one. In brief,
the regular expression sear h looks for and nds the word even though it is
outside the marked region.
In the se ond manifestation of the bug, the region is whitespa e at the
end of the bu er. Ema s says `Sear h failed'. What happens is that the
true-or-false-test in the while loop tests true, so the sear h expression is
exe uted. But sin e there are no more words in the bu er, the sear h fails.
In both manifestations of the bug, the sear h extends or attempts to
extend outside of the region.
The solution is to limit the sear h to the region|this is a fairly simple
a tion, but as you may have ome to expe t, it is not quite as simple as you
might think.
As we have seen, the re-sear h-forward fun tion takes a sear h pattern
as its rst argument. But in addition to this rst, mandatory argument, it
a epts three optional arguments. The optional se ond argument bounds the
sear h. The optional third argument, if t, auses the fun tion to return nil
rather than signal an error if the sear h fails. The optional fourth argument
is a repeat ount. (In Ema s, you an see a fun tion's do umentation by
typing C-h f, the name of the fun tion, and then hRETi.)
In the ount-words-region de nition, the value of the end of the region
is held by the variable end whi h is passed as an argument to the fun -
tion. Thus, we an add end as an argument to the regular expression sear h
expression:
(re-sear h-forward "\\w+\\W*" end)
However, if you make only this hange to the ount-words-region de ni-
tion and then test the new version of the de nition on a stret h of whitespa e,
you will re eive an error message saying `Sear h failed'.
What happens is this: the sear h is limited to the region, and fails as
you expe t be ause there are no word- onstituent hara ters in the region.
Sin e it fails, we re eive an error message. But we do not want to re eive an
error message in this ase; we want to re eive the message that "The region
does NOT have any words."
172 Chapter 13: Counting: Repetition and Regexps

The solution to this problem is to provide re-sear h-forward with a


third argument of t, whi h auses the fun tion to return nil rather than
signal an error if the sear h fails.
However, if you make this hange and try it, you will see the message
\Counting words in region ... " and . . . you will keep on seeing that message
. . . , until you type C-g (keyboard-quit).
Here is what happens: the sear h is limited to the region, as before, and
it fails be ause there are no word- onstituent hara ters in the region, as
expe ted. Consequently, the re-sear h-forward expression returns nil.
It does nothing else. In parti ular, it does not move point, whi h it does
as a side e e t if it nds the sear h target. After the re-sear h-forward
expression returns nil, the next expression in the while loop is evaluated.
This expression in rements the ount. Then the loop repeats. The true-or-
false-test tests true be ause the value of point is still less than the value of
end, sin e the re-sear h-forward expression did not move point. . . . and
the y le repeats . . .
The ount-words-region de nition requires yet another modi ation,
to ause the true-or-false-test of the while loop to test false if the sear h
fails. Put another way, there are two onditions that must be satis ed in the
true-or-false-test before the word ount variable is in remented: point must
still be within the region and the sear h expression must have found a word
to ount.
Sin e both the rst ondition and the se ond ondition must be true
together, the two expressions, the region test and the sear h expression, an
be joined with an and spe ial form and embedded in the while loop as the
true-or-false-test, like this:
(and (< (point) end) (re-sear h-forward "\\w+\\W*" end t))
(For information about and, see Se tion 12.4, \forward-paragraph: a Gold-
mine of Fun tions", page 155.)
The re-sear h-forward expression returns t if the sear h su eeds and
as a side e e t moves point. Consequently, as words are found, point is
moved through the region. When the sear h expression fails to nd another
word, or when point rea hes the end of the region, the true-or-false-test tests
false, the while loop exists, and the ount-words-region fun tion displays
one or other of its messages.
After in orporating these nal hanges, the ount-words-region works
without bugs (or at least, without bugs that I have found!). Here is what it
looks like:
;;; Final version: while
(defun ount-words-region (beginning end)
"Print number of words in the region."
(intera tive "r")
(message "Counting words in region ... ")
Count Words Re ursively 173

;;; 1. Set up appropriate onditions.


(save-ex ursion
(let (( ount 0))
(goto- har beginning)
;;; 2. Run the while loop.
(while (and (< (point) end)
(re-sear h-forward "\\w+\\W*" end t))
(setq ount (1+ ount)))
;;; 3. Send a message to the user.
( ond ((zerop ount)
(message
"The region does NOT have any words."))
((= 1 ount)
(message
"The region has 1 word."))
(t
(message
"The region has %d words." ount))))))

13.2 Count Words Re ursively


You an write the fun tion for ounting words re ursively as well as with
a while loop. Let's see how this is done.
First, we need to re ognize that the ount-words-region fun tion has
three jobs: it sets up the appropriate onditions for ounting to o ur; it
ounts the words in the region; and it sends a message to the user telling
how many words there are.
If we write a single re ursive fun tion to do everything, we will re eive
a message for every re ursive all. If the region ontains 13 words, we will
re eive thirteen messages, one right after the other. We don't want this!
Instead, we must write two fun tions to do the job, one of whi h (the re ur-
sive fun tion) will be used inside of the other. One fun tion will set up the
onditions and display the message; the other will return the word ount.
Let us start with the fun tion that auses the message to be displayed.
We an ontinue to all this ount-words-region.
This is the fun tion that the user will all. It will be intera tive. Indeed,
it will be similar to our previous versions of this fun tion, ex ept that it
will all re ursive- ount-words to determine how many words are in the
region.
174 Chapter 13: Counting: Repetition and Regexps

We an readily onstru t a template for this fun tion, based on our pre-
vious versions:

;; Re ursive version; uses regular expression sear h


(defun ount-words-region (beginning end)
"do umentation..."
(intera tive-expression...)

;;; 1. Set up appropriate onditions.


(explanatory message )
(set-up fun tions ...

;;; 2. Count the words.


re ursive all

;;; 3. Send a message to the user.


message providing word ount))

The de nition looks straightforward, ex ept that somehow the ount re-
turned by the re ursive all must be passed to the message displaying the
word ount. A little thought suggests that this an be done by making use
of a let expression: we an bind a variable in the varlist of a let expression
to the number of words in the region, as returned by the re ursive all; and
then the ond expression, using binding, an display the value to the user.

Often, one thinks of the binding within a let expression as somehow


se ondary to the `primary' work of a fun tion. But in this ase, what you
might onsider the `primary' job of the fun tion, ounting words, is done
within the let expression.

Using let, the fun tion de nition looks like this:

(defun ount-words-region (beginning end)


"Print number of words in the region."
(intera tive "r")
;;; 1. Set up appropriate onditions.
(message "Counting words in region ... ")
(save-ex ursion
(goto- har beginning)
;;; 2. Count the words.
(let (( ount (re ursive- ount-words end)))
Count Words Re ursively 175

;;; 3. Send a message to the user.


( ond ((zerop ount)
(message
"The region does NOT have any words."))
((= 1 ount)
(message
"The region has 1 word."))
(t
(message
"The region has %d words." ount))))))
Next, we need to write the re ursive ounting fun tion.
A re ursive fun tion has at least three parts: the `do-again-test', the
`next-step-expression', and the re ursive all.
The do-again-test determines whether the fun tion will or will not be
alled again. Sin e we are ounting words in a region and an use a fun tion
that moves point forward for every word, the do-again-test an he k whether
point is still within the region. The do-again-test should nd the value of
point and determine whether point is before, at, or after the value of the
end of the region. We an use the point fun tion to lo ate point. Clearly,
we must pass the value of the end of the region to the re ursive ounting
fun tion as an argument.
In addition, the do-again-test should also test whether the sear h nds a
word. If it does not, the fun tion should not all itself again.
The next-step-expression hanges a value so that when the re ursive fun -
tion is supposed to stop alling itself, it stops. More pre isely, the next-step-
expression hanges a value so that at the right time, the do-again-test stops
the re ursive fun tion from alling itself again. In this ase, the next-step-
expression an be the expression that moves point forward, word by word.
The third part of a re ursive fun tion is the re ursive all.
Somewhere, also, we also need a part that does the `work' of the fun tion,
a part that does the ounting. A vital part!
But already, we have an outline of the re ursive ounting fun tion:
(defun re ursive- ount-words (region-end)
"do umentation..."
do-again-test
next-step-expression
re ursive all )
Now we need to ll in the slots. Let's start with the simplest ases rst:
if point is at or beyond the end of the region, there annot be any words in
the region, so the fun tion should return zero. Likewise, if the sear h fails,
there are no words to ount, so the fun tion should return zero.
On the other hand, if point is within the region and the sear h su eeds,
the fun tion should all itself again.
176 Chapter 13: Counting: Repetition and Regexps

Thus, the do-again-test should look like this:


(and (< (point) region-end)
(re-sear h-forward "\\w+\\W*" region-end t))
Note that the sear h expression is part of the do-again-test|the fun tion
returns t if its sear h su eeds and nil if it fails. (See Se tion 13.1.1, \The
Whitespa e Bug in ount-words-region", page 170, for an explanation of
how re-sear h-forward works.)
The do-again-test is the true-or-false test of an if lause. Clearly, if
the do-again-test su eeds, the then-part of the if lause should all the
fun tion again; but if it fails, the else-part should return zero sin e either
point is outside the region or the sear h failed be ause there were no words
to nd.
But before onsidering the re ursive all, we need to onsider the next-
step-expression. What is it? Interestingly, it is the sear h part of the do-
again-test.
In addition to returning t or nil for the do-again-test, re-sear h-
forward moves point forward as a side e e t of a su essful sear h. This is
the a tion that hanges the value of point so that the re ursive fun tion stops
alling itself when point ompletes its movement through the region. Con-
sequently, the re-sear h-forward expression is the next-step-expression.
In outline, then, the body of the re ursive- ount-words fun tion looks
like this:
(if do-again-test-and-next-step- ombined
;; then
re ursive- all-returning- ount
;; else
return-zero )
How to in orporate the me hanism that ounts?
If you are not used to writing re ursive fun tions, a question like this an
be troublesome. But it an and should be approa hed systemati ally.
We know that the ounting me hanism should be asso iated in some
way with the re ursive all. Indeed, sin e the next-step-expression moves
point forward by one word, and sin e a re ursive all is made for ea h word,
the ounting me hanism must be an expression that adds one to the value
returned by a all to re ursive- ount-words.
Consider several ases:
 If there are two words in the region, the fun tion should return a value
resulting from adding one to the value returned when it ounts the rst
word, plus the number returned when it ounts the remaining words in
the region, whi h in this ase is one.
 If there is one word in the region, the fun tion should return a value
resulting from adding one to the value returned when it ounts that
Count Words Re ursively 177

word, plus the number returned when it ounts the remaining words in
the region, whi h in this ase is zero.
 If there are no words in the region, the fun tion should return zero.
From the sket h we an see that the else-part of the if returns zero for
the ase of no words. This means that the then-part of the if must return
a value resulting from adding one to the value returned from a ount of the
remaining words.
The expression will look like this, where 1+ is a fun tion that adds one
to its argument.
(1+ (re ursive- ount-words region-end))
The whole re ursive- ount-words fun tion will then look like this:
(defun re ursive- ount-words (region-end)
"do umentation..."

;;; 1. do-again-test
(if (and (< (point) region-end)
(re-sear h-forward "\\w+\\W*" region-end t))
;;; 2. then-part: the re ursive all
(1+ (re ursive- ount-words region-end))

;;; 3. else-part
0))
Let's examine how this works:
If there are no words in the region, the else part of the if expression is
evaluated and onsequently the fun tion returns zero.
If there is one word in the region, the value of point is less than the value
of region-end and the sear h su eeds. In this ase, the true-or-false-test
of the if expression tests true, and the then-part of the if expression is
evaluated. The ounting expression is evaluated. This expression returns a
value (whi h will be the value returned by the whole fun tion) that is the
sum of one added to the value returned by a re ursive all.
Meanwhile, the next-step-expression has aused point to jump over the
rst (and in this ase only) word in the region. This means that when
(re ursive- ount-words region-end) is evaluated a se ond time, as a
result of the re ursive all, the value of point will be equal to or greater
than the value of region end. So this time, re ursive- ount-words will
return zero. The zero will be added to one, and the original evaluation of
re ursive- ount-words will return one plus zero, whi h is one, whi h is
the orre t amount.
Clearly, if there are two words in the region, the rst all to re ursive-
ount-words returns one added to the value returned by alling re ursive-
ount-words on a region ontaining the remaining word|that is, it adds
one to one, produ ing two, whi h is the orre t amount.
178 Chapter 13: Counting: Repetition and Regexps

Similarly, if there are three words in the region, the rst all to
re ursive- ount-words returns one added to the value returned by alling
re ursive- ount-words on a region ontaining the remaining two words|
and so on and so on.

With full do umentation the two fun tions look like this:

The re ursive fun tion:

(defun re ursive- ount-words (region-end)


"Number of words between point and REGION-END."
;;; 1. do-again-test
(if (and (< (point) region-end)
(re-sear h-forward "\\w+\\W*" region-end t))
;;; 2. then-part: the re ursive all
(1+ (re ursive- ount-words region-end))

;;; 3. else-part
0))

The wrapper:

;;; Re ursive version


(defun ount-words-region (beginning end)
"Print number of words in the region.
Words are defined as at least one word- onstituent
hara ter followed by at least one hara ter that is
not a word- onstituent. The buffer's syntax table
determines whi h hara ters these are."
(intera tive "r")
(message "Counting words in region ... ")
(save-ex ursion
(goto- har beginning)
(let (( ount (re ursive- ount-words end)))
( ond ((zerop ount)
(message
"The region does NOT have any words."))
((= 1 ount)
(message "The region has 1 word."))
(t
(message
"The region has %d words." ount))))))
Exer ise: Counting Pun tuation 179

13.3 Exer ise: Counting Pun tuation


Using a while loop, write a fun tion to ount the number of pun tuation
marks in a region|period, omma, semi olon, olon, ex lamation mark, and
question mark. Do the same using re ursion.
180 Chapter 13: Counting: Repetition and Regexps
What to Count? 181

14 Counting Words in a defun


Our next proje t is to ount the number of words in a fun tion de nition.
Clearly, this an be done using some variant of ount-word-region. See
Chapter 13, \Counting Words: Repetition and Regexps", page 167. If we
are just going to ount the words in one de nition, it is easy enough to
mark the de nition with the C-M-h (mark-defun) ommand, and then all
ount-word-region.
However, I am more ambitious: I want to ount the words and symbols
in every de nition in the Ema s sour es and then print a graph that shows
how many fun tions there are of ea h length: how many ontain 40 to 49
words or symbols, how many ontain 50 to 59 words or symbols, and so on.
I have often been urious how long a typi al fun tion is, and this will tell.
Des ribed in one phrase, the histogram proje t is daunting; but divided
into numerous small steps, ea h of whi h we an take one at a time, the
proje t be omes less fearsome. Let us onsider what the steps must be:
 First, write a fun tion to ount the words in one de nition. This in ludes
the problem of handling symbols as well as words.
 Se ond, write a fun tion to list the numbers of words in ea h fun tion
in a le. This fun tion an use the ount-words-in-defun fun tion.
 Third, write a fun tion to list the numbers of words in ea h fun tion
in ea h of several les. This entails automati ally nding the various
les, swit hing to them, and ounting the words in the de nitions within
them.
 Fourth, write a fun tion to onvert the list of numbers that we reated
in step three to a form that will be suitable for printing as a graph.
 Fifth, write a fun tion to print the results as a graph.
This is quite a proje t! But if we take ea h step slowly, it will not be
diÆ ult.

14.1 What to Count?


When we rst start thinking about how to ount the words in a fun tion
de nition, the rst question is (or ought to be) what are we going to ount?
When we speak of `words' with respe t to a Lisp fun tion de nition, we are
a tually speaking, in large part, of `symbols'. For example, the following
multiply-by-seven fun tion ontains the ve symbols defun, multiply-
by-seven, number, *, and 7. In addition, in the do umentation string, it
ontains the four words `Multiply', `NUMBER', `by', and `seven'. The symbol
`number' is repeated, so the de nition ontains a total of ten words and
symbols.
(defun multiply-by-seven (number)
"Multiply NUMBER by seven."
(* 7 number))
182 Chapter 14: Counting Words in a defun

However, if we mark the multiply-by-seven de nition with C-M-h (mark-


defun), and then all ount-words-region on it, we will nd that ount-
words-region laims the de nition has eleven words, not ten! Something is
wrong!
The problem is twofold: ount-words-region does not ount the `*' as
a word, and it ounts the single symbol, multiply-by-seven, as ontaining
three words. The hyphens are treated as if they were interword spa es rather
than intraword onne tors: `multiply-by-seven' is ounted as if it were
written `multiply by seven'.
The ause of this onfusion is the regular expression sear h within the
ount-words-region de nition that moves point forward word by word. In
the anoni al version of ount-words-region, the regexp is:
"\\w+\\W*"
This regular expression is a pattern de ning one or more word onstituent
hara ters possibly followed by one or more hara ters that are not word
onstituents. What is meant by `word onstituent hara ters' brings us to
the issue of syntax, whi h is worth a se tion of its own.

14.2 What Constitutes a Word or Symbol?


Ema s treats di erent hara ters as belonging to di erent syntax ate-
gories. For example, the regular expression, `\\w+', is a pattern spe ifying
one or more word onstituent hara ters. Word onstituent hara ters are
members of one syntax ategory. Other syntax ategories in lude the lass
of pun tuation hara ters, su h as the period and the omma, and the lass
of whitespa e hara ters, su h as the blank spa e and the tab hara ter.
(For more information, see se tion \The Syntax Table" in The GNU Ema s
Manual, and se tion \Syntax Tables" in The GNU Ema s Lisp Referen e
Manual.)
Syntax tables spe ify whi h hara ters belong to whi h ategories. Usu-
ally, a hyphen is not spe i ed as a `word onstituent hara ter'. Instead,
it is spe i ed as being in the ` lass of hara ters that are part of symbol
names but not words.' This means that the ount-words-region fun tion
treats it in the same way it treats an interword white spa e, whi h is why
ount-words-region ounts `multiply-by-seven' as three words.
There are two ways to ause Ema s to ount `multiply-by-seven' as
one symbol: modify the syntax table or modify the regular expression.
We ould rede ne a hyphen as a word onstituent hara ter by modifying
the syntax table that Ema s keeps for ea h mode. This a tion would serve
our purpose, ex ept that a hyphen is merely the most ommon hara ter
within symbols that is not typi ally a word onstituent hara ter; there are
others, too.
The ount-words-in-defun Fun tion 183

Alternatively, we an rede ne the regular expression used in the ount-


words de nition so as to in lude symbols. This pro edure has the merit of
larity, but the task is a little tri ky.
The rst part is simple enough: the pattern must mat h \at least one
hara ter that is a word or symbol onstituent". Thus:
"\\(\\w\\|\\s_\\)+"
The `\\(' is the rst part of the grouping onstru t that in ludes the `\\w'
and the `\\s_' as alternatives, separated by the `\\|'. The `\\w' mat hes any
word- onstituent hara ter and the `\\s_' mat hes any hara ter that is part
of a symbol name but not a word- onstituent hara ter. The `+' following
the group indi ates that the word or symbol onstituent hara ters must be
mat hed at least on e.
However, the se ond part of the regexp is more diÆ ult to design. What
we want is to follow the rst part with \optionally one or more hara ters
that are not onstituents of a word or symbol". At rst, I thought I ould
de ne this with the following:
"\\(\\W\\|\\S_\\)*"
The upper ase `W' and `S' mat h hara ters that are not word or symbol
onstituents. Unfortunately, this expression mat hes any hara ter that is
either not a word onstituent or not a symbol onstituent. This mat hes any
hara ter!
I then noti ed that every word or symbol in my test region was followed
by white spa e (blank spa e, tab, or newline). So I tried pla ing a pattern
to mat h one or more blank spa es after the pattern for one or more word
or symbol onstituents. This failed, too. Words and symbols are often
separated by whitespa e, but in a tual ode parentheses may follow symbols
and pun tuation may follow words. So nally, I designed a pattern in whi h
the word or symbol onstituents are followed optionally by hara ters that
are not white spa e and then followed optionally by white spa e.
Here is the full regular expression:
"\\(\\w\\|\\s_\\)+[^ \t\n℄*[ \t\n℄*"

14.3 The ount-words-in-defun Fun tion


We have seen that there are several ways to write a ount-word-region
fun tion. To write a ount-words-in-defun, we need merely adapt one of
these versions.
The version that uses a while loop is easy to understand, so I am going to
adapt that. Be ause ount-words-in-defun will be part of a more omplex
program, it need not be intera tive and it need not display a message but
just return the ount. These onsiderations simplify the de nition a little.
On the other hand, ount-words-in-defun will be used within a bu er
that ontains fun tion de nitions. Consequently, it is reasonable to ask that
184 Chapter 14: Counting Words in a defun

the fun tion determine whether it is alled when point is within a fun tion
de nition, and if it is, to return the ount for that de nition. This adds
omplexity to the de nition, but saves us from needing to pass arguments
to the fun tion.
These onsiderations lead us to prepare the following template:
(defun ount-words-in-defun ()
"do umentation..."
(set up...
(while loop...)
return ount)
As usual, our job is to ll in the slots.
First, the set up.
We are presuming that this fun tion will be alled within a bu er on-
taining fun tion de nitions. Point will either be within a fun tion de nition
or not. For ount-words-in-defun to work, point must move to the begin-
ning of the de nition, a ounter must start at zero, and the ounting loop
must stop when point rea hes the end of the de nition.
The beginning-of-defun fun tion sear hes ba kwards for an opening
delimiter su h as a `(' at the beginning of a line, and moves point to that
position, or else to the limit of the sear h. In pra ti e, this means that
beginning-of-defun moves point to the beginning of an en losing or pre-
eding fun tion de nition, or else to the beginning of the bu er. We an use
beginning-of-defun to pla e point where we wish to start.
The while loop requires a ounter to keep tra k of the words or symbols
being ounted. A let expression an be used to reate a lo al variable for
this purpose, and bind it to an initial value of zero.
The end-of-defun fun tion works like beginning-of-defun ex ept that
it moves point to the end of the de nition. end-of-defun an be used as part
of an expression that determines the position of the end of the de nition.
The set up for ount-words-in-defun takes shape rapidly: rst we move
point to the beginning of the de nition, then we reate a lo al variable to
hold the ount, and nally, we re ord the position of the end of the de nition
so the while loop will know when to stop looping.
The ode looks like this:
(beginning-of-defun)
(let (( ount 0)
(end (save-ex ursion (end-of-defun) (point))))
The ode is simple. The only slight ompli ation is likely to on ern end: it
is bound to the position of the end of the de nition by a save-ex ursion
expression that returns the value of point after end-of-defun temporarily
moves it to the end of the de nition.
The se ond part of the ount-words-in-defun, after the set up, is the
while loop.
The ount-words-in-defun Fun tion 185

The loop must ontain an expression that jumps point forward word by
word and symbol by symbol, and another expression that ounts the jumps.
The true-or-false-test for the while loop should test true so long as point
should jump forward, and false when point is at the end of the de nition.
We have already rede ned the regular expression for this (see Se tion 14.2,
\Syntax", page 182), so the loop is straightforward:
(while (and (< (point) end)
(re-sear h-forward
"\\(\\w\\|\\s_\\)+[^ \t\n℄*[ \t\n℄*" end t)
(setq ount (1+ ount)))

The third part of the fun tion de nition returns the ount of words and
symbols. This part is the last expression within the body of the let expres-
sion, and an be, very simply, the lo al variable ount, whi h when evaluated
returns the ount.
Put together, the ount-words-in-defun de nition looks like this:
(defun ount-words-in-defun ()
"Return the number of words and symbols in a defun."
(beginning-of-defun)
(let (( ount 0)
(end (save-ex ursion (end-of-defun) (point))))
(while
(and (< (point) end)
(re-sear h-forward
"\\(\\w\\|\\s_\\)+[^ \t\n℄*[ \t\n℄*"
end t))
(setq ount (1+ ount)))
ount))

How to test this? The fun tion is not intera tive, but it is easy to put a
wrapper around the fun tion to make it intera tive; we an use almost the
same ode as for the re ursive version of ount-words-region:
;;; Intera tive version.
(defun ount-words-defun ()
"Number of words and symbols in a fun tion definition."
(intera tive)
(message
"Counting words and symbols in fun tion definition ... ")
(let (( ount ( ount-words-in-defun)))
( ond
((zerop ount)
(message
"The definition does NOT have any words or symbols."))
186 Chapter 14: Counting Words in a defun

((= 1 ount)
(message
"The definition has 1 word or symbol."))
(t
(message
"The definition has %d words or symbols." ount)))))
Let's re-use C- = as a onvenient keybinding:
(global-set-key "\C- =" ' ount-words-defun)
Now we an try out ount-words-defun: install both ount-words-in-
defun and ount-words-defun, and set the keybinding, and then pla e the
ursor within the following de nition:
(defun multiply-by-seven (number)
"Multiply NUMBER by seven."
(* 7 number))
) 10
Su ess! The de nition has 10 words and symbols.
The next problem is to ount the numbers of words and symbols in several
de nitions within a single le.

14.4 Count Several defuns Within a File


A le su h as `simple.el' may have 80 or more fun tion de nitions within
it. Our long term goal is to olle t statisti s on many les, but as a rst
step, our immediate goal is to olle t statisti s on one le.
The information will be a series of numbers, ea h number being the length
of a fun tion de nition. We an store the numbers in a list.
We know that we will want to in orporate the information regarding one
le with information about many other les; this means that the fun tion
for ounting de nition lengths within one le need only return the list of
lengths. It need not and should not display any messages.
The word ount ommands ontain one expression to jump point forward
word by word and another expression to ount the jumps. The fun tion to
return the lengths of de nitions an be designed to work the same way, with
one expression to jump point forward de nition by de nition and another
expression to onstru t the lengths' list.
This statement of the problem makes it elementary to write the fun tion
de nition. Clearly, we will start the ount at the beginning of the le, so
the rst ommand will be (goto- har (point-min)). Next, we start the
while loop; and the true-or-false test of the loop an be a regular expression
sear h for the next fun tion de nition|so long as the sear h su eeds, point
is moved forward and then the body of the loop is evaluated. The body needs
an expression that onstru ts the lengths' list. ons, the list onstru tion
ommand, an be used to reate the list. That is almost all there is to it.
lengths-list-file in Detail 187

Here is what this fragment of ode looks like:


(goto- har (point-min))
(while (re-sear h-forward "^(defun" nil t)
(setq lengths-list
( ons ( ount-words-in-defun) lengths-list)))
What we have left out is the me hanism for nding the le that ontains
the fun tion de nitions.
In previous examples, we either used this, the Info le, or we swit hed
ba k and forth to some other bu er, su h as the `*s rat h*' bu er.
Finding a le is a new pro ess that we have not yet dis ussed.

14.5 Find a File


To nd a le in Ema s, you use the C-x C-f (find-file) ommand. This
ommand is almost, but not quite right for the lengths problem.
Let's look at the sour e for find-file (you an use the find-tag om-
mand or C-h f (des ribe-fun tion) to nd the sour e of a fun tion):
(defun find-file (filename)
"Edit file FILENAME.
Swit h to a buffer visiting file FILENAME,
reating one if none already exists."
(intera tive "FFind file: ")
(swit h-to-buffer (find-file-nosele t filename)))
The de nition possesses short but omplete do umentation and an in-
tera tive spe i ation that prompts you for a le name when you use the
ommand intera tively. The body of the de nition ontains two fun tions,
find-file-nosele t and swit h-to-buffer.
A ording to its do umentation as shown by C-h f (the des ribe-
fun tion ommand), the find-file-nosele t fun tion reads the named
le into a bu er and returns the bu er. However, the bu er is not sele ted.
Ema s does not swit h its attention (or yours if you are using find-file-
nosele t) to the named bu er. That is what swit h-to-buffer does: it
swit hes the bu er to whi h Ema s attention is dire ted; and it swit hes the
bu er displayed in the window to the new bu er. We have dis ussed bu er
swit hing elsewhere. (See Se tion 2.3, \Swit hing Bu ers", page 26.)
In this histogram proje t, we do not need to display ea h le on the
s reen as the program determines the length of ea h de nition within it.
Instead of employing swit h-to-buffer, we an work with set-buffer,
whi h redire ts the attention of the omputer program to a di erent bu er
but does not redisplay it on the s reen. So instead of alling on find-file
to do the job, we must write our own expression.
The task is easy: use find-file-nosele t and set-buffer.
188 Chapter 14: Counting Words in a defun

14.6 lengths-list-file in Detail


The ore of the lengths-list-file fun tion is a while loop ontaining
a fun tion to move point forward `defun by defun' and a fun tion to ount
the number of words and symbols in ea h defun. This ore must be sur-
rounded by fun tions that do various other tasks, in luding nding the le,
and ensuring that point starts out at the beginning of the le. The fun tion
de nition looks like this:
(defun lengths-list-file (filename)
"Return list of definitions' lengths within FILE.
The returned list is a list of numbers.
Ea h number is the number of words or
symbols in one fun tion definition."
(message "Working on `%s' ... " filename)
(save-ex ursion
(let ((buffer (find-file-nosele t filename))
(lengths-list))
(set-buffer buffer)
(setq buffer-read-only t)
(widen)
(goto- har (point-min))
(while (re-sear h-forward "^(defun" nil t)
(setq lengths-list
( ons ( ount-words-in-defun) lengths-list)))
(kill-buffer buffer)
lengths-list)))
The fun tion is passed one argument, the name of the le on whi h it will
work. It has four lines of do umentation, but no intera tive spe i ation.
Sin e people worry that a omputer is broken if they don't see anything
going on, the rst line of the body is a message.
The next line ontains a save-ex ursion that returns Ema s' attention
to the urrent bu er when the fun tion ompletes. This is useful in ase you
embed this fun tion in another fun tion that presumes point is restored to
the original bu er.
In the varlist of the let expression, Ema s nds the le and binds the
lo al variable buffer to the bu er ontaining the le. At the same time,
Ema s reates lengths-list as a lo al variable.
Next, Ema s swit hes its attention to the bu er.
In the following line, Ema s makes the bu er read-only. Ideally, this line
is not ne essary. None of the fun tions for ounting words and symbols in a
fun tion de nition should hange the bu er. Besides, the bu er is not going
to be saved, even if it were hanged. This line is entirely the onsequen e
of great, perhaps ex essive, aution. The reason for the aution is that this
fun tion and those it alls work on the sour es for Ema s and it is very
lengths-list-file in Detail 189

in onvenient if they are inadvertently modi ed. It goes without saying that
I did not realize a need for this line until an experiment went awry and
started to modify my Ema s sour e les . . .
Next omes a all to widen the bu er if it is narrowed. This fun tion
is usually not needed|Ema s reates a fresh bu er if none already exists;
but if a bu er visiting the le already exists Ema s returns that one. In
this ase, the bu er may be narrowed and must be widened. If we wanted
to be fully `user-friendly', we would arrange to save the restri tion and the
lo ation of point, but we won't.
The (goto- har (point-min)) expression moves point to the beginning
of the bu er.
Then omes a while loop in whi h the `work' of the fun tion is arried out.
In the loop, Ema s determines the length of ea h de nition and onstru ts
a lengths' list ontaining the information.
Ema s kills the bu er after working through it. This is to save spa e
inside of Ema s. My version of Ema s 19 ontained over 300 sour e les
of interest; Ema s 21 ontains over 800 sour e les. Another fun tion will
apply lengths-list-file to ea h of the les.
Finally, the last expression within the let expression is the lengths-list
variable; its value is returned as the value of the whole fun tion.
You an try this fun tion by installing it in the usual fashion. Then pla e
your ursor after the following expression and type C-x C-e (eval-last-
sexp).
(lengths-list-file
"/usr/lo al/share/ema s/21.0.100/lisp/ema s-lisp/debug.el")
(You may need to hange the pathname of the le; the one here worked
with GNU Ema s version 21.0.100. To hange the expression, opy it to the
`*s rat h*' bu er and edit it.
(Also, to see the full length of the list, rather than a trun ated version, you
may have to evaluate the following:
( ustom-set-variables '(eval-expression-print-length nil))
(See Se tion 16.2, \Setting Variables with def ustom", page 214. Then
evaluate the lengths-list-file expression.)
190 Chapter 14: Counting Words in a defun

The lengths' list for `debug.el' takes less than a se ond to produ e and
looks like this:
(77 95 85 87 131 89 50 25 44 44 68 35 64 45 17 34 167 457)

(Using my old ma hine, the version 19 lengths' list for `debug.el' took
seven se onds to produ e and looked like this:
(75 41 80 62 20 45 44 68 45 12 34 235)

(The newer version of `debug.el' ontains more defuns than the earlier
one; and my new ma hine is mu h faster than the old one.)
Note that the length of the last de nition in the le is rst in the list.

14.7 Count Words in defuns in Di erent Files


In the previous se tion, we reated a fun tion that returns a list of the
lengths of ea h de nition in a le. Now, we want to de ne a fun tion to
return a master list of the lengths of the de nitions in a list of les.
Working on ea h of a list of les is a repetitious a t, so we an use either
a while loop or re ursion.
The design using a while loop is routine. The argument passed the fun -
tion is a list of les. As we saw earlier (see Se tion 11.1.1, \Loop Example",
page 122), you an write a while loop so that the body of the loop is evalu-
ated if su h a list ontains elements, but to exit the loop if the list is empty.
For this design to work, the body of the loop must ontain an expression
that shortens the list ea h time the body is evaluated, so that eventually the
list is empty. The usual te hnique is to set the value of the list to the value
of the dr of the list ea h time the body is evaluated.
The template looks like this:
(while test-whether-list-is-empty
body ...
set-list-to- dr-of-list)
Also, we remember that a while loop returns nil (the result of evaluat-
ing the true-or-false-test), not the result of any evaluation within its body.
(The evaluations within the body of the loop are done for their side e e ts.)
However, the expression that sets the lengths' list is part of the body|and
that is the value that we want returned by the fun tion as a whole. To do
this, we en lose the while loop within a let expression, and arrange that
the last element of the let expression ontains the value of the lengths' list.
(See \Loop Example with an In rementing Counter", page 125.)
The append Fun tion 191

These onsiderations lead us dire tly to the fun tion itself:


;;; Use while loop.
(defun lengths-list-many-files (list-of-files)
"Return list of lengths of defuns in LIST-OF-FILES."
(let (lengths-list)

;;; true-or-false-test
(while list-of-files
(setq lengths-list
(append
lengths-list

;;; Generate a lengths' list.


(lengths-list-file
(expand-file-name ( ar list-of-files)))))
;;; Make les' list shorter.
(setq list-of-files ( dr list-of-files)))

;;; Return nal value of lengths' list.


lengths-list))
expand-file-name is a built-in fun tion that onverts a le name to the
absolute, long, path name form of the dire tory in whi h the fun tion is
alled.
Thus, if expand-file-name is alled on debug.el when Ema s is visiting
the `/usr/lo al/share/ema s/21.0.100/lisp/ema s-lisp/' dire tory,
debug.el
be omes
/usr/lo al/share/ema s/21.0.100/lisp/ema s-lisp/debug.el
The only other new element of this fun tion de nition is the as yet un-
studied fun tion append, whi h merits a short se tion for itself.

14.7.1 The append Fun tion


The append fun tion atta hes one list to another. Thus,
(append '(1 2 3 4) '(5 6 7 8))
produ es the list
(1 2 3 4 5 6 7 8)
This is exa tly how we want to atta h two lengths' lists produ ed by
lengths-list-file to ea h other. The results ontrast with ons,
( ons '(1 2 3 4) '(5 6 7 8))
192 Chapter 14: Counting Words in a defun

whi h onstru ts a new list in whi h the rst argument to ons be omes the
rst element of the new list:
((1 2 3 4) 5 6 7 8)

14.8 Re ursively Count Words in Di erent Files


Besides a while loop, you an work on ea h of a list of les with re ursion.
A re ursive version of lengths-list-many-files is short and simple.
The re ursive fun tion has the usual parts: the `do-again-test', the `next-
step-expression', and the re ursive all. The `do-again-test' determines
whether the fun tion should all itself again, whi h it will do if the list-
of-files ontains any remaining elements; the `next-step-expression' resets
the list-of-files to the dr of itself, so eventually the list will be empty;
and the re ursive all alls itself on the shorter list. The omplete fun tion
is shorter than this des ription!
(defun re ursive-lengths-list-many-files (list-of-files)
"Return list of lengths of ea h defun in LIST-OF-FILES."
(if list-of-files ; do-again-test
(append
(lengths-list-file
(expand-file-name ( ar list-of-files)))
(re ursive-lengths-list-many-files
( dr list-of-files)))))
In a senten e, the fun tion returns the lengths' list for the rst of the list-
of-files appended to the result of alling itself on the rest of the list-
of-files.
Here is a test of re ursive-lengths-list-many-files, along with the
results of running lengths-list-file on ea h of the les individually.
Install re ursive-lengths-list-many-files and lengths-list-file,
if ne essary, and then evaluate the following expressions. You may need to
hange the les' pathnames; those here work when this Info le and the
Ema s sour es are lo ated in their ustomary pla es. To hange the expres-
sions, opy them to the `*s rat h*' bu er, edit them, and then evaluate
them.
The results are shown after the `)'. (These results are for les from
Ema s Version 21.0.100; les from other versions of Ema s may produ e
di erent results.)
( d "/usr/lo al/share/ema s/21.0.100/")

(lengths-list-file "./lisp/ma ros.el")


) (273 263 456 90)
(lengths-list-file "./lisp/mail/mailalias.el")
) (38 32 26 77 174 180 321 198 324)
Sorting Lists 193

(lengths-list-file "./lisp/makesum.el")
) (85 181)
(re ursive-lengths-list-many-files
'("./lisp/ma ros.el"
"./lisp/mail/mailalias.el"
"./lisp/makesum.el"))
) (273 263 456 90 38 32 26 77 174 180 321 198 324 85 181)
The re ursive-lengths-list-many-files fun tion produ es the out-
put we want.
The next step is to prepare the data in the list for display in a graph.

14.9 Prepare the Data for Display in a Graph


The re ursive-lengths-list-many-files fun tion returns a list of
numbers. Ea h number re ords the length of a fun tion de nition. What
we need to do now is transform this data into a list of numbers suitable for
generating a graph. The new list will tell how many fun tions de nitions
ontain less than 10 words and symbols, how many ontain between 10 and
19 words and symbols, how many ontain between 20 and 29 words and
symbols, and so on.
In brief, we need to go through the lengths' list produ ed by the
re ursive-lengths-list-many-files fun tion and ount the number of
defuns within ea h range of lengths, and produ e a list of those numbers.
Based on what we have done before, we an readily foresee that it should
not be too hard to write a fun tion that ` drs' down the lengths' list, looks
at ea h element, determines whi h length range it is in, and in rements a
ounter for that range.
However, before beginning to write su h a fun tion, we should onsider
the advantages of sorting the lengths' list rst, so the numbers are ordered
from smallest to largest. First, sorting will make it easier to ount the
numbers in ea h range, sin e two adja ent numbers will either be in the
same length range or in adja ent ranges. Se ond, by inspe ting a sorted list,
we an dis over the highest and lowest number, and thereby determine the
largest and smallest length range that we will need.

14.9.1 Sorting Lists


Ema s ontains a fun tion to sort lists, alled (as you might guess) sort.
The sort fun tion takes two arguments, the list to be sorted, and a predi ate
that determines whether the rst of two list elements is \less" than the
se ond.
As we saw earlier (see Se tion 1.8.4, \Using the Wrong Type Obje t as
an Argument", page 14), a predi ate is a fun tion that determines whether
194 Chapter 14: Counting Words in a defun

some property is true or false. The sort fun tion will reorder a list a ord-
ing to whatever property the predi ate uses; this means that sort an be
used to sort non-numeri lists by non-numeri riteria|it an, for example,
alphabetize a list.
The < fun tion is used when sorting a numeri list. For example,
(sort '(4 8 21 17 33 7 21 7) '<)
produ es this:
(4 7 7 8 17 21 21 33)
(Note that in this example, both the arguments are quoted so that the
symbols are not evaluated before being passed to sort as arguments.)
Sorting the list returned by the re ursive-lengths-list-many-files
fun tion is straightforward; it uses the < fun tion:
(sort
(re ursive-lengths-list-many-files
'("../lisp/ma ros.el"
"../lisp/mailalias.el"
"../lisp/makesum.el"))
'<
whi h produ es:
(85 86 116 122 154 176 179 265)
(Note that in this example, the rst argument to sort is not quoted, sin e
the expression must be evaluated so as to produ e the list that is passed to
sort.)

14.9.2 Making a List of Files


The re ursive-lengths-list-many-files fun tion requires a list of
les as its argument. For our test examples, we onstru ted su h a list by
hand; but the Ema s Lisp sour e dire tory is too large for us to do for that.
Instead, we will write a fun tion to do the job for us. In this fun tion, we
will use both a while loop and a re ursive all.
We did not have to write a fun tion like this for older versions of GNU
Ema s, sin e they pla ed all the `.el' les in one dire tory. Instead, we were
able to use the dire tory-files fun tion, whi h lists the names of les that
mat h a spe i ed pattern within a single dire tory.
However, re ent versions of Ema s pla e Ema s Lisp les in sub-
dire tories of the top level `lisp' dire tory. This re-arrangement eases
navigation. For example, all the mail related les are in a `lisp'
sub-dire tory alled `mail'. But at the same time, this arrangement for es
us to reate a le listing fun tion that des ends into the sub-dire tories.
We an reate this fun tion, alled files-in-below-dire tory, using
familiar fun tions su h as ar, nth dr, and substring in onjun tion with
an existing fun tion alled dire tory-files-and-attributes. This latter
Making a List of Files 195

fun tion not only lists all the lenames in a dire tory, in luding the names
of sub-dire tories, but also their attributes.
To restate our goal: to reate a fun tion that will enable us to feed
lenames to re ursive-lengths-list-many-files as a list that looks like
this (but with more elements):
("../lisp/ma ros.el"
"../lisp/mail/rmail.el"
"../lisp/makesum.el")
The dire tory-files-and-attributes fun tion returns a list of lists.
Ea h of the lists within the main list onsists of 13 elements. The rst
element is a string that ontains the name of the le { whi h, in GNU/Linux,
may be a `dire tory le', that is to say, a le with the spe ial attributes of
a dire tory. The se ond element of the list is t for a dire tory, a string for
symboli link (the string is the name linked to), or nil.
For example, the rst `.el' le in the `lisp/' dire tory is `abbrev.el'.
Its name is `/usr/lo al/share/ema s/21.0.100/lisp/abbrev.el' and it
is not a dire tory or a symboli link.
This is how dire tory-files-and-attributes lists that le and its
attributes:
("/usr/lo al/share/ema s/21.0.100/lisp/abbrev.el"
nil
1
1000
100
(15019 32380)
(14883 48041)
(15214 49336)
11583
"-rw-rw-r--"
t
341385
776)
On the other hand, `mail/' is a dire tory within the `lisp/' dire tory.
The beginning of its listing looks like this:
("/usr/lo al/share/ema s/21.0.100/lisp/mail"
t
...
)
(Look at the do umentation of file-attributes to learn about the dif-
ferent attributes. Bear in mind that the file-attributes fun tion does not
list the lename, so its rst element is dire tory-files-and-attributes's
se ond element.)
196 Chapter 14: Counting Words in a defun

We will want our new fun tion, files-in-below-dire tory, to list the
`.el' les in the dire tory it is told to he k, and in any dire tories below
that dire tory.
This gives us a hint on how to onstru t files-in-below-dire tory:
within a dire tory, the fun tion should add `.el' lenames to a list; and if,
within a dire tory, the fun tion omes upon a sub-dire tory, it should go
into that sub-dire tory and repeat its a tions.
However, we should note that every dire tory ontains a name that refers
to itself, alled `.', (\dot") and a name that refers to its parent dire tory,
alled `..' (\double dot"). (In `/', the root dire tory, `..' refers to itself,
sin e `/' has no parent.) Clearly, we do not want our files-in-below-
dire tory fun tion to enter those dire tories, sin e they always lead us,
dire tly or indire tly, to the urrent dire tory.
Consequently, our files-in-below-dire tory fun tion must do several
tasks:
 Che k to see whether it is looking at a lename that ends in `.el'; and
if so, add its name to a list.
 Che k to see whether it is looking at a lename that is the name of a
dire tory; and if so,
Che k to see whether it is looking at `.' or `..'; and if so skip it.
Or else, go into that dire tory and repeat the pro ess.

Let's write a fun tion de nition to do these tasks. We will use a while
loop to move from one lename to another within a dire tory, he king what
needs to be done; and we will use a re ursive all to repeat the a tions on
ea h sub-dire tory. The re ursive pattern is `a umulate' (see \Re ursive
Pattern: a umulate ", page 142), using append as the ombiner.
Here is the fun tion:
(defun files-in-below-dire tory (dire tory)
"List the .el files in DIRECTORY and in its sub-dire tories."
;; Although the fun tion will be used non-intera tively,
;; it will be easier to test if we make it intera tive.
;; The dire tory will have a name su h as
;; "/usr/lo al/share/ema s/21.0.100/lisp/"
(intera tive "DDire tory name: ")
(let (el-files-list
( urrent-dire tory-list
(dire tory-files-and-attributes dire tory t)))
;; while we are in the urrent dire tory
(while urrent-dire tory-list
Counting fun tion de nitions 197

( ond
;; he k to see whether filename ends in `.el'
;; and if so, append its name to a list.
((equal ".el" (substring ( ar ( ar urrent-dire tory-list)) -3))
(setq el-files-list
( ons ( ar ( ar urrent-dire tory-list)) el-files-list)))
;; he k whether filename is that of a dire tory
((eq t ( ar ( dr ( ar urrent-dire tory-list))))
;; de ide whether to skip or re urse
(if
(equal (or "." "..")
(substring ( ar ( ar urrent-dire tory-list)) -1))
;; then do nothing if filename is that of
;; urrent dire tory or parent
()
;; else des end into the dire tory and repeat the pro ess
(setq el-files-list
(append
(files-in-below-dire tory
( ar ( ar urrent-dire tory-list)))
el-files-list)))))
;; move to the next filename in the list; this also
;; shortens the list so the while loop eventually omes to an end
(setq urrent-dire tory-list ( dr urrent-dire tory-list)))
;; return the filenames
el-files-list))
The files-in-below-dire tory dire tory-files fun tion takes one
argument, the name of a dire tory.
Thus, on my system,
(length
(files-in-below-dire tory "/usr/lo al/share/ema s/21.0.100/lisp/"))
tells me that my version 21.0.100 Lisp sour es dire tory ontains 754 `.el'
les.
files-in-below-dire tory returns a list in reverse alphabeti al order.
An expression to sort the list in alphabeti al order looks like this:
(sort
(files-in-below-dire tory "/usr/lo al/share/ema s/21.0.100/lisp/")
'string-lessp)

14.9.3 Counting fun tion de nitions


Our immediate goal is to generate a list that tells us how many fun tion
de nitions ontain fewer than 10 words and symbols, how many ontain
198 Chapter 14: Counting Words in a defun

between 10 and 19 words and symbols, how many ontain between 20 and
29 words and symbols, and so on.
With a sorted list of numbers, this is easy: ount how many elements
of the list are smaller than 10, then, after moving past the numbers just
ounted, ount how many are smaller than 20, then, after moving past the
numbers just ounted, ount how many are smaller than 30, and so on. Ea h
of the numbers, 10, 20, 30, 40, and the like, is one larger than the top of
that range. We an all the list of su h numbers the top-of-ranges list.
If we wished, we ould generate this list automati ally, but it is simpler
to write a list manually. Here it is:
(defvar top-of-ranges
'(10 20 30 40 50
60 70 80 90 100
110 120 130 140 150
160 170 180 190 200
210 220 230 240 250
260 270 280 290 300)
"List spe ifying ranges for `defuns-per-range'.")

To hange the ranges, we edit this list.


Next, we need to write the fun tion that reates the list of the number of
de nitions within ea h range. Clearly, this fun tion must take the sorted-
lengths and the top-of-ranges lists as arguments.
The defuns-per-range fun tion must do two things again and again: it
must ount the number of de nitions within a range spe i ed by the urrent
top-of-range value; and it must shift to the next higher value in the top-
of-ranges list after ounting the number of de nitions in the urrent range.
Sin e ea h of these a tions is repetitive, we an use while loops for the job.
One loop ounts the number of de nitions in the range de ned by the urrent
top-of-range value, and the other loop sele ts ea h of the top-of-range values
in turn.
Several entries of the sorted-lengths list are ounted for ea h range;
this means that the loop for the sorted-lengths list will be inside the loop
for the top-of-ranges list, like a small gear inside a big gear.
The inner loop ounts the number of de nitions within the range. It is a
simple ounting loop of the type we have seen before. (See Se tion 11.1.3, \A
loop with an in rementing ounter", page 124.) The true-or-false test of the
loop tests whether the value from the sorted-lengths list is smaller than
the urrent value of the top of the range. If it is, the fun tion in rements
the ounter and tests the next value from the sorted-lengths list.
Counting fun tion de nitions 199

The inner loop looks like this:


(while length-element-smaller-than-top-of-range
(setq number-within-range (1+ number-within-range))
(setq sorted-lengths ( dr sorted-lengths)))
The outer loop must start with the lowest value of the top-of-ranges
list, and then be set to ea h of the su eeding higher values in turn. This
an be done with a loop like this:
(while top-of-ranges
body-of-loop...
(setq top-of-ranges ( dr top-of-ranges)))
Put together, the two loops look like this:
(while top-of-ranges

;; Count the number of elements within the urrent range.


(while length-element-smaller-than-top-of-range
(setq number-within-range (1+ number-within-range))
(setq sorted-lengths ( dr sorted-lengths)))

;; Move to next range.


(setq top-of-ranges ( dr top-of-ranges)))
In addition, in ea h ir uit of the outer loop, Ema s should re ord the
number of de nitions within that range (the value of number-within-range)
in a list. We an use ons for this purpose. (See Se tion 7.2, \ ons",
page 83.)
The ons fun tion works ne, ex ept that the list it onstru ts will on-
tain the number of de nitions for the highest range at its beginning and the
number of de nitions for the lowest range at its end. This is be ause ons
atta hes new elements of the list to the beginning of the list, and sin e the
two loops are working their way through the lengths' list from the lower end
rst, the defuns-per-range-list will end up largest number rst. But we
will want to print our graph with smallest values rst and the larger later.
The solution is to reverse the order of the defuns-per-range-list. We an
do this using the nreverse fun tion, whi h reverses the order of a list.
For example,
(nreverse '(1 2 3 4))
produ es:
(4 3 2 1)
Note that the nreverse fun tion is \destru tive"|that is, it hanges
the list to whi h it is applied; this ontrasts with the ar and dr fun tions,
whi h are non-destru tive. In this ase, we do not want the original defuns-
per-range-list, so it does not matter that it is destroyed. (The reverse
fun tion provides a reversed opy of a list, leaving the original list as is.)
200 Chapter 14: Counting Words in a defun

Put all together, the defuns-per-range looks like this:


(defun defuns-per-range (sorted-lengths top-of-ranges)
"SORTED-LENGTHS defuns in ea h TOP-OF-RANGES range."
(let ((top-of-range ( ar top-of-ranges))
(number-within-range 0)
defuns-per-range-list)
;; Outer loop.
(while top-of-ranges
;; Inner loop.
(while (and
;; Need number for numeri test.
( ar sorted-lengths)
(< ( ar sorted-lengths) top-of-range))
;; Count number of de nitions within urrent range.
(setq number-within-range (1+ number-within-range))
(setq sorted-lengths ( dr sorted-lengths)))

;; Exit inner loop but remain within outer loop.


(setq defuns-per-range-list
( ons number-within-range defuns-per-range-list))
(setq number-within-range 0) ; Reset ount to zero.
;; Move to next range.
(setq top-of-ranges ( dr top-of-ranges))
;; Spe ify next top of range value.
(setq top-of-range ( ar top-of-ranges)))
;; Exit outer loop and ount the number of defuns larger than
;; the largest top-of-range value.
(setq defuns-per-range-list
( ons
(length sorted-lengths)
defuns-per-range-list))
;; Return a list of the number of de nitions within ea h range,
;; smallest to largest.
(nreverse defuns-per-range-list)))
Counting fun tion de nitions 201

The fun tion is straightforward ex ept for one subtle feature. The true-or-
false test of the inner loop looks like this:
(and ( ar sorted-lengths)
(< ( ar sorted-lengths) top-of-range))

instead of like this:


(< ( ar sorted-lengths) top-of-range)

The purpose of the test is to determine whether the rst item in the
sorted-lengths list is less than the value of the top of the range.
The simple version of the test works ne unless the sorted-lengths
list has a nil value. In that ase, the ( ar sorted-lengths) expression
fun tion returns nil. The < fun tion annot ompare a number to nil,
whi h is an empty list, so Ema s signals an error and stops the fun tion
from attempting to ontinue to exe ute.
The sorted-lengths list always be omes nil when the ounter rea hes
the end of the list. This means that any attempt to use the defuns-per-
range fun tion with the simple version of the test will fail.
We solve the problem by using the ( ar sorted-lengths) expression in
onjun tion with the and expression. The ( ar sorted-lengths) expres-
sion returns a non-nil value so long as the list has at least one number within
it, but returns nil if the list is empty. The and expression rst evaluates
the ( ar sorted-lengths) expression, and if it is nil, returns false without
evaluating the < expression. But if the ( ar sorted-lengths) expression
returns a non-nil value, the and expression evaluates the < expression, and
returns that value as the value of the and expression.
This way, we avoid an error. See Se tion 12.4, \forward-paragraph: a
Goldmine of Fun tions", page 155, for more information about and.
Here is a short test of the defuns-per-range fun tion. First, evaluate
the expression that binds (a shortened) top-of-ranges list to the list of
values, then evaluate the expression for binding the sorted-lengths list,
and then evaluate the defuns-per-range fun tion.
;; (Shorter list than we will use later.)
(setq top-of-ranges
'(110 120 130 140 150
160 170 180 190 200))

(setq sorted-lengths
'(85 86 110 116 122 129 154 176 179 200 265 300 300))

(defuns-per-range sorted-lengths top-of-ranges)


202 Chapter 14: Counting Words in a defun

The list returned looks like this:


(2 2 2 0 0 1 0 2 0 0 4)
Indeed, there are two elements of the sorted-lengths list smaller than 110,
two elements between 110 and 119, two elements between 120 and 129, and
so on. There are four elements with a value of 200 or larger.
Readying a Graph 203

15 Readying a Graph
Our goal is to onstru t a graph showing the numbers of fun tion de ni-
tions of various lengths in the Ema s lisp sour es.
As a pra ti al matter, if you were reating a graph, you would probably
use a program su h as gnuplot to do the job. (gnuplot is ni ely integrated
into GNU Ema s.) In this ase, however, we reate one from s rat h, and
in the pro ess we will re-a quaint ourselves with some of what we learned
before and learn more.
In this hapter, we will rst write a simple graph printing fun tion. This
rst de nition will be a prototype, a rapidly written fun tion that enables
us to re onnoiter this unknown graph-making territory. We will dis over
dragons, or nd that they are myth. After s outing the terrain, we will feel
more on dent and enhan e the fun tion to label the axes automati ally.
Sin e Ema s is designed to be exible and work with all kinds of terminals,
in luding hara ter-only terminals, the graph will need to be made from one
of the `typewriter' symbols. An asterisk will do; as we enhan e the graph-
printing fun tion, we an make the hoi e of symbol a user option.
We an all this fun tion graph-body-print; it will take a numbers-list
as its only argument. At this stage, we will not label the graph, but only
print its body.
The graph-body-print fun tion inserts a verti al olumn of asterisks for
ea h element in the numbers-list. The height of ea h line is determined by
the value of that element of the numbers-list.
Inserting olumns is a repetitive a t; that means that this fun tion an
be written either with a while loop or re ursively.
Our rst hallenge is to dis over how to print a olumn of asterisks.
Usually, in Ema s, we print hara ters onto a s reen horizontally, line by
line, by typing. We have two routes we an follow: write our own olumn-
insertion fun tion or dis over whether one exists in Ema s.
To see whether there is one in Ema s, we an use the M-x apropos om-
mand. This ommand is like the C-h a ( ommand-apropos) ommand, ex-
ept that the latter nds only those fun tions that are ommands. The
M-x apropos ommand lists all symbols that mat h a regular expression,
in luding fun tions that are not intera tive.
What we want to look for is some ommand that prints or inserts olumns.
Very likely, the name of the fun tion will ontain either the word `print' or
the word `insert' or the word ` olumn'. Therefore, we an simply type M-x
apropos RET print\|insert\| olumn RET and look at the result. On my
system, this ommand takes quite some time, and then produ es a list of
79 fun tions and variables. S anning down the list, the only fun tion that
looks as if it might do the job is insert-re tangle.
204 Chapter 15: Readying a Graph

Indeed, this is the fun tion we want; its do umentation says:


insert-re tangle:
Insert text of RECTANGLE with upper left orner at point.
RECTANGLE's first line is inserted at point,
its se ond line is inserted at a point verti ally under point, et .
RECTANGLE should be a list of strings.
We an run a qui k test, to make sure it does what we expe t of it.
Here is the result of pla ing the ursor after the insert-re tangle ex-
pression and typing C-u C-x C-e (eval-last-sexp). The fun tion inserts
the strings `"first"', `"se ond"', and `"third"' at and below point. Also
the fun tion returns nil.
(insert-re tangle '("first" "se ond" "third"))first
se ond
third
nil
Of ourse, we won't be inserting the text of the insert-re tangle expres-
sion itself into the bu er in whi h we are making the graph, but will all
the fun tion from our program. We shall, however, have to make sure that
point is in the bu er at the pla e where the insert-re tangle fun tion will
insert its olumn of strings.
If you are reading this in Info, you an see how this works by swit hing
to another bu er, su h as the `*s rat h*' bu er, pla ing point somewhere
in the bu er, typing M-:, typing the insert-re tangle expression into the
minibu er at the prompt, and then typing hRETi. This auses Ema s to
evaluate the expression in the minibu er, but to use as the value of point
the position of point in the `*s rat h*' bu er. (M-: is the keybinding for
eval-expression.)
We nd when we do this that point ends up at the end of the last inserted
line|that is to say, this fun tion moves point as a side-e e t. If we were to
repeat the ommand, with point at this position, the next insertion would
be below and to the right of the previous insertion. We don't want this! If
we are going to make a bar graph, the olumns need to be beside ea h other.
So we dis over that ea h y le of the olumn-inserting while loop must
reposition point to the pla e we want it, and that pla e will be at the top,
not the bottom, of the olumn. Moreover, we remember that when we print
a graph, we do not expe t all the olumns to be the same height. This means
that the top of ea h olumn may be at a di erent height from the previous
one. We annot simply reposition point to the same line ea h time, but
moved over to the right|or perhaps we an. . .
We are planning to make the olumns of the bar graph out of asterisks.
The number of asterisks in the olumn is the number spe i ed by the urrent
element of the numbers-list. We need to onstru t a list of asterisks of the
right length for ea h all to insert-re tangle. If this list onsists solely of
the requisite number of asterisks, then we will have position point the right
Readying a Graph 205

number of lines above the base for the graph to print orre tly. This ould
be diÆ ult.
Alternatively, if we an gure out some way to pass insert-re tangle
a list of the same length ea h time, then we an pla e point on the same line
ea h time, but move it over one olumn to the right for ea h new olumn.
If we do this, however, some of the entries in the list passed to insert-
re tangle must be blanks rather than asterisks. For example, if the max-
imum height of the graph is 5, but the height of the olumn is 3, then
insert-re tangle requires an argument that looks like this:
(" " " " "*" "*" "*")
This last proposal is not so diÆ ult, so long as we an determine the
olumn height. There are two ways for us to spe ify the olumn height:
we an arbitrarily state what it will be, whi h would work ne for graphs
of that height; or we an sear h through the list of numbers and use the
maximum height of the list as the maximum height of the graph. If the
latter operation were diÆ ult, then the former pro edure would be easiest,
but there is a fun tion built into Ema s that determines the maximum of
its arguments. We an use that fun tion. The fun tion is alled max and it
returns the largest of all its arguments, whi h must be numbers. Thus, for
example,
(max 3 4 6 5 7 3)
returns 7. (A orresponding fun tion alled min returns the smallest of all
its arguments.)
However, we annot simply all max on the numbers-list; the max fun -
tion expe ts numbers as its argument, not a list of numbers. Thus, the
following expression,
(max '(3 4 6 5 7 3))
produ es the following error message;
Wrong type of argument: number-or-marker-p, (3 4 6 5 7 3)
We need a fun tion that passes a list of arguments to a fun tion. This
fun tion is apply. This fun tion `applies' its rst argument (a fun tion) to
its remaining arguments, the last of whi h may be a list.
For example,
(apply 'max 3 4 7 3 '(4 8 5))
returns 8.
(In identally, I don't know how you would learn of this fun tion without
a book su h as this. It is possible to dis over other fun tions, like sear h-
forward or insert-re tangle, by guessing at a part of their names and
then using apropos. Even though its base in metaphor is lear|`apply'
its rst argument to the rest|I doubt a novi e would ome up with that
parti ular word when using apropos or other aid. Of ourse, I ould be
wrong; after all, the fun tion was rst named by someone who had to invent
it.)
206 Chapter 15: Readying a Graph

The se ond and subsequent arguments to apply are optional, so we an


use apply to all a fun tion and pass the elements of a list to it, like this,
whi h also returns 8:
(apply 'max '(4 8 5))
This latter way is how we will use apply. The re ursive-lengths-
list-many-files fun tion returns a numbers' list to whi h we an apply
max (we ould also apply max to the sorted numbers' list; it does not matter
whether the list is sorted or not.)
Hen e, the operation for nding the maximum height of the graph is this:
(setq max-graph-height (apply 'max numbers-list))
Now we an return to the question of how to reate a list of strings for a
olumn of the graph. Told the maximum height of the graph and the number
of asterisks that should appear in the olumn, the fun tion should return a
list of strings for the insert-re tangle ommand to insert.
Ea h olumn is made up of asterisks or blanks. Sin e the fun tion is
passed the value of the height of the olumn and the number of asterisks in
the olumn, the number of blanks an be found by subtra ting the number
of asterisks from the height of the olumn. Given the number of blanks and
the number of asterisks, two while loops an be used to onstru t the list:
;;; First version.
(defun olumn-of-graph (max-graph-height a tual-height)
"Return list of strings that is one olumn of a graph."
(let ((insert-list nil)
(number-of-top-blanks
(- max-graph-height a tual-height)))
;; Fill in asterisks.
(while (> a tual-height 0)
(setq insert-list ( ons "*" insert-list))
(setq a tual-height (1- a tual-height)))
;; Fill in blanks.
(while (> number-of-top-blanks 0)
(setq insert-list ( ons " " insert-list))
(setq number-of-top-blanks
(1- number-of-top-blanks)))
;; Return whole list.
insert-list))

If you install this fun tion and then evaluate the following expression you
will see that it returns the list as desired:
( olumn-of-graph 5 3)
Readying a Graph 207

returns
(" " " " "*" "*" "*")

As written, olumn-of-graph ontains a major aw: the symbols used


for the blank and for the marked entries in the olumn are `hard- oded' as
a spa e and asterisk. This is ne for a prototype, but you, or another user,
may wish to use other symbols. For example, in testing the graph fun tion,
you many want to use a period in pla e of the spa e, to make sure the point
is being repositioned properly ea h time the insert-re tangle fun tion is
alled; or you might want to substitute a `+' sign or other symbol for the
asterisk. You might even want to make a graph- olumn that is more than
one display olumn wide. The program should be more exible. The way to
do that is to repla e the blank and the asterisk with two variables that we an
all graph-blank and graph-symbol and de ne those variables separately.
Also, the do umentation is not well written. These onsiderations lead
us to the se ond version of the fun tion:
(defvar graph-symbol "*"
"String used as symbol in graph, usually an asterisk.")
(defvar graph-blank " "
"String used as blank in graph, usually a blank spa e.
graph-blank must be the same number of olumns wide
as graph-symbol.")

(For an explanation of defvar, see Se tion 8.4, \Initializing a Variable with


defvar", page 100.)
;;; Se ond version.
(defun olumn-of-graph (max-graph-height a tual-height)
"Return MAX-GRAPH-HEIGHT strings; ACTUAL-HEIGHT are graph-symbols.

The graph-symbols are ontiguous entries at the end


of the list.
The list will be inserted as one olumn of a graph.
The strings are either graph-blank or graph-symbol."
(let ((insert-list nil)
(number-of-top-blanks
(- max-graph-height a tual-height)))
;; Fill in graph-symbols.
(while (> a tual-height 0)
(setq insert-list ( ons graph-symbol insert-list))
(setq a tual-height (1- a tual-height)))
208 Chapter 15: Readying a Graph

;; Fill in graph-blanks.
(while (> number-of-top-blanks 0)
(setq insert-list ( ons graph-blank insert-list))
(setq number-of-top-blanks
(1- number-of-top-blanks)))

;; Return whole list.


insert-list))
If we wished, we ould rewrite olumn-of-graph a third time to provide
optionally for a line graph as well as for a bar graph. This would not be
hard to do. One way to think of a line graph is that it is no more than a
bar graph in whi h the part of ea h bar that is below the top is blank. To
onstru t a olumn for a line graph, the fun tion rst onstru ts a list of
blanks that is one shorter than the value, then it uses ons to atta h a graph
symbol to the list; then it uses ons again to atta h the `top blanks' to the
list.
It is easy to see how to write su h a fun tion, but sin e we don't need it,
we will not do it. But the job ould be done, and if it were done, it would
be done with olumn-of-graph. Even more important, it is worth noting
that few hanges would have to be made anywhere else. The enhan ement,
if we ever wish to make it, is simple.
Now, nally, we ome to our rst a tual graph printing fun tion. This
prints the body of a graph, not the labels for the verti al and horizontal
axes, so we an all this graph-body-print.

15.1 The graph-body-print Fun tion


After our preparation in the pre eding se tion, the graph-body-print
fun tion is straightforward. The fun tion will print olumn after olumn of
asterisks and blanks, using the elements of a numbers' list to spe ify the
number of asterisks in ea h olumn. This is a repetitive a t, whi h means
we an use a de rementing while loop or re ursive fun tion for the job. In
this se tion, we will write the de nition using a while loop.
The olumn-of-graph fun tion requires the height of the graph as an
argument, so we should determine and re ord that as a lo al variable.
This leads us to the following template for the while loop version of this
fun tion:
(defun graph-body-print (numbers-list)
"do umentation..."
(let ((height ...
...))
(while numbers-list
insert- olumns-and-reposition-point
(setq numbers-list ( dr numbers-list)))))
The graph-body-print Fun tion 209

We need to ll in the slots of the template.


Clearly, we an use the (apply 'max numbers-list) expression to deter-
mine the height of the graph.
The while loop will y le through the numbers-list one element at a
time. As it is shortened by the (setq numbers-list ( dr numbers-list))
expression, the ar of ea h instan e of the list is the value of the argument
for olumn-of-graph.
At ea h y le of the while loop, the insert-re tangle fun tion inserts
the list returned by olumn-of-graph. Sin e the insert-re tangle fun -
tion moves point to the lower right of the inserted re tangle, we need to save
the lo ation of point at the time the re tangle is inserted, move ba k to that
position after the re tangle is inserted, and then move horizontally to the
next pla e from whi h insert-re tangle is alled.
If the inserted olumns are one hara ter wide, as they will be if sin-
gle blanks and asterisks are used, the repositioning ommand is simply
(forward- har 1); however, the width of a olumn may be greater than one.
This means that the repositioning ommand should be written (forward-
har symbol-width). The symbol-width itself is the length of a graph-
blank and an be found using the expression (length graph-blank). The
best pla e to bind the symbol-width variable to the value of the width of
graph olumn is in the varlist of the let expression.
These onsiderations lead to the following fun tion de nition:
(defun graph-body-print (numbers-list)
"Print a bar graph of the NUMBERS-LIST.
The numbers-list onsists of the Y-axis values."

(let ((height (apply 'max numbers-list))


(symbol-width (length graph-blank))
from-position)
(while numbers-list
(setq from-position (point))
(insert-re tangle
( olumn-of-graph height ( ar numbers-list)))
(goto- har from-position)
(forward- har symbol-width)
;; Draw graph olumn by olumn.
(sit-for 0)
(setq numbers-list ( dr numbers-list)))
;; Pla e point for X axis labels.
(forward-line height)
(insert "\n")
))
210 Chapter 15: Readying a Graph

The one unexpe ted expression in this fun tion is the (sit-for 0) expres-
sion in the while loop. This expression makes the graph printing operation
more interesting to wat h than it would be otherwise. The expression auses
Ema s to `sit' or do nothing for a zero length of time and then redraw the
s reen. Pla ed here, it auses Ema s to redraw the s reen olumn by olumn.
Without it, Ema s would not redraw the s reen until the fun tion exits.
We an test graph-body-print with a short list of numbers.
1. Install graph-symbol, graph-blank, olumn-of-graph, whi h are in
Chapter 15, \Readying a Graph", page 203, and graph-body-print.
2. Copy the following expression:
(graph-body-print '(1 2 3 4 6 4 3 5 7 6 5 2 3))
3. Swit h to the `*s rat h*' bu er and pla e the ursor where you want
the graph to start.
4. Type M-: (eval-expression).
5. Yank the graph-body-print expression into the minibu er with C-y
(yank).
6. Press hRETi to evaluate the graph-body-print expression.
Ema s will print a graph like this:
*
* **
* ****
*** ****
********* *
************
*************

15.2 The re ursive-graph-body-print Fun tion


The graph-body-print fun tion may also be written re ursively. The
re ursive solution is divided into two parts: an outside `wrapper' that uses
a let expression to determine the values of several variables that need only
be found on e, su h as the maximum height of the graph, and an inside
fun tion that is alled re ursively to print the graph.
Need for Printed Axes 211

The `wrapper' is un ompli ated:


(defun re ursive-graph-body-print (numbers-list)
"Print a bar graph of the NUMBERS-LIST.
The numbers-list onsists of the Y-axis values."
(let ((height (apply 'max numbers-list))
(symbol-width (length graph-blank))
from-position)
(re ursive-graph-body-print-internal
numbers-list
height
symbol-width)))
The re ursive fun tion is a little more diÆ ult. It has four parts: the
`do-again-test', the printing ode, the re ursive all, and the `next-step-
expression'. The `do-again-test' is an if expression that determines whether
the numbers-list ontains any remaining elements; if it does, the fun -
tion prints one olumn of the graph using the printing ode and alls itself
again. The fun tion alls itself again a ording to the value produ ed by the
`next-step-expression' whi h auses the all to a t on a shorter version of the
numbers-list.
(defun re ursive-graph-body-print-internal
(numbers-list height symbol-width)
"Print a bar graph.
Used within re ursive-graph-body-print fun tion."
(if numbers-list
(progn
(setq from-position (point))
(insert-re tangle
( olumn-of-graph height ( ar numbers-list)))
(goto- har from-position)
(forward- har symbol-width)
(sit-for 0) ; Draw graph olumn by olumn.
(re ursive-graph-body-print-internal
( dr numbers-list) height symbol-width))))
After installation, this expression an be tested; here is a sample:
(re ursive-graph-body-print '(3 2 5 6 7 5 3 4 6 4 3 2 1))
Here is what re ursive-graph-body-print produ es:
*
** *
**** *
**** ***
* *********
************
*************
212 Chapter 15: Readying a Graph

Either of these two fun tions, graph-body-print or re ursive-graph-


body-print, reate the body of a graph.

15.3 Need for Printed Axes


A graph needs printed axes, so you an orient yourself. For a do-on e
proje t, it may be reasonable to draw the axes by hand using Ema s' Pi ture
mode; but a graph drawing fun tion may be used more than on e.
For this reason, I have written enhan ements to the basi print-graph-
body fun tion that automati ally print labels for the horizontal and verti al
axes. Sin e the label printing fun tions do not ontain mu h new material,
I have pla ed their des ription in an appendix. See Appendix C, \A Graph
with Labelled Axes", page 255.

15.4 Exer ise


Write a line graph version of the graph printing fun tions.
Site-wide Initialization Files 213

16 Your `.ema s' File


\You don't have to like Ema s to like it" { this seemingly paradoxi al
statement is the se ret of GNU Ema s. The plain, `out of the box' Ema s is
a generi tool. Most people who use it, ustomize it to suit themselves.
GNU Ema s is mostly written in Ema s Lisp; this means that by writing
expressions in Ema s Lisp you an hange or extend Ema s.
There are those who appre iate Ema s' default on guration. After all,
Ema s starts you in C mode when you edit a C le, starts you in Fortran
mode when you edit a Fortran le, and starts you in Fundamental mode
when you edit an unadorned le. This all makes sense, if you do not know
who is going to use Ema s. Who knows what a person hopes to do with an
unadorned le? Fundamental mode is the right default for su h a le, just
as C mode is the right default for editing C ode. But when you do know
who is going to use Ema s|you, yourself|then it makes sense to ustomize
Ema s.
For example, I seldom want Fundamental mode when I edit an otherwise
undistinguished le; I want Text mode. This is why I ustomize Ema s: so
it suits me.
You an ustomize and extend Ema s by writing or adapting a `~/.ema s'
le. This is your personal initialization le; its ontents, written in Ema s
Lisp, tell Ema s what to do.1
A `~/.ema s' le ontains Ema s Lisp ode. You an write this ode
yourself; or you an use Ema s' ustomize feature to write the ode for
you. You an ombine your own expressions and auto-written Customize
expressions in your `.ema s' le.
(I myself prefer to write my own expressions, ex ept for those, parti ularly
fonts, that I nd easier to manipulate using the ustomize ommand. I
ombine the two methods.)
Most of this hapter is about writing expressions yourself. It des ribes
a simple `.ema s' le; for more information, see se tion \The Init File" in
The GNU Ema s Manual, and se tion \The Init File" in The GNU Ema s
Lisp Referen e Manual.

16.1 Site-wide Initialization Files


In addition to your personal initialization le, Ema s automati ally loads
various site-wide initialization les, if they exist. These have the same form
as your `.ema s' le, but are loaded by everyone.
1 You may also add `.el' to `~/.ema s' and all it a `~/.ema s.el' le. In the past,
you were forbidden to type the extra keystrokes that the name `~/.ema s.el' requires,
but now you may. The new format is onsistent with the Ema s Lisp le naming
onventions; the old format saves typing.
214 Chapter 16: Your `.ema s' File

Two site-wide initialization les, `site-load.el' and `site-init.el',


are loaded into Ema s and then `dumped' if a `dumped' version of Ema s is
reated, as is most ommon. (Dumped opies of Ema s load more qui kly.
However, on e a le is loaded and dumped, a hange to it does not lead
to a hange in Ema s unless you load it yourself or re-dump Ema s. See
se tion \Building Ema s" in The GNU Ema s Lisp Referen e Manual, and
the `INSTALL' le.)
Three other site-wide initialization les are loaded automati ally ea h
time you start Ema s, if they exist. These are `site-start.el', whi h is
loaded before your `.ema s' le, and `default.el', and the terminal type
le, whi h are both loaded after your `.ema s' le.
Settings and de nitions in your `.ema s' le will overwrite on i ting
settings and de nitions in a `site-start.el' le, if it exists; but the settings
and de nitions in a `default.el' or terminal type le will overwrite those in
your `.ema s' le. (You an prevent interferen e from a terminal type le by
setting term-file-prefix to nil. See Se tion 16.11, \A Simple Extension",
page 224.)
The `INSTALL' le that omes in the distribution ontains des riptions of
the `site-init.el' and `site-load.el' les.
The `loadup.el', `startup.el', and `loaddefs.el' les ontrol loading.
These les are in the `lisp' dire tory of the Ema s distribution and are
worth perusing.
The `loaddefs.el' le ontains a good many suggestions as to what to
put into your own `.ema s' le, or into a site-wide initialization le.

16.2 Spe ifying Variables using def ustom


You an spe ify variables using def ustom so that you and others an
then an use Ema s' ustomize feature to set their values. (You annot use
ustomize to write fun tion de nitions; but you an write defuns in your
`.ema s' le. Indeed, you an write any Lisp expression in your `.ema s'
le.)
The ustomize feature depends on the def ustom spe ial form. Al-
though you an use defvar or setq for variables that users set, the
def ustom spe ial form is designed for the job.
You an use your knowledge of defvar for writing the rst three argu-
ments for def ustom. The rst argument to def ustom is the name of the
variable. The se ond argument is the variable's initial value, if any; and this
value is set only if the value has not already been set. The third argument
is the do umentation.
The fourth and subsequent arguments to def ustom spe ify types and
options; these are not featured in defvar. (These arguments are optional.)
Ea h of these arguments onsists of a keyword followed by a value. Ea h
keyword starts with the hara ter :.
Spe ifying Variables using def ustom 215

For example, the ustomizable user option variable text-mode-hook


looks like this:
(def ustom text-mode-hook nil
"Normal hook run when entering Text mode and many related modes."
:type 'hook
:options '(turn-on-auto-fill flyspell-mode)
:group 'data)
The name of the variable is text-mode-hook; it has no default value; and
its do umentation string tells you what it does.
The :type keyword tells Ema s what kind of data text-mode-hook
should be set to and how to display the value in a Customization bu er.
The :options keyword spe i es a suggested list of values for the vari-
able. Currently, you an use :options only for a hook. The list is only a
suggestion; it is not ex lusive; a person who sets the variable may set it to
other values; the list shown following the :options keyword is intended to
o er onvenient hoi es to a user.
Finally, the :group keyword tells the Ema s Customization ommand in
whi h group the variable is lo ated. This tells where to nd it.
For more information, see se tion \Writing Customization De nitions"
in The GNU Ema s Lisp Referen e Manual.
Consider text-mode-hook as an example.
There are two ways to ustomize this variable. You an use the us-
tomization ommand or write the appropriate expressions yourself.
Using the ustomization ommand, you an type:
M-x ustomize
and nd that the group for editing les of data is alled `data'. Enter that
group. Text Mode Hook is the rst member. You an li k on its various
options to set the values. After you li k on the button to
Save for Future Sessions
Ema s will write an expression into your `.ema s' le. It will look like this:
( ustom-set-variables
;; ustom-set-variables was added by Custom --
;; don't edit or ut/paste it!
;; Your init file should ontain only one su h instan e.
'(text-mode-hook (quote (turn-on-auto-fill text-mode-hook-identify))))
(The text-mode-hook-identify fun tion tells toggle-text-mode-auto-
fill whi h bu ers are in Text mode.)
In spite of the warning, you ertainly may edit, ut, and paste the ex-
pression! I do all time. The purpose of the warning is to s are those who
do not know what they are doing, so they do not inadvertently generate an
error.
216 Chapter 16: Your `.ema s' File

The ustom-set-variables works somewhat di erently than a setq.


While I have never learned the di eren es, I do modify the ustom-set-
variables expressions in my `.ema s' le by hand: I make the hanges
in what appears to me to be a reasonable manner and have not had any
problems. Others prefer to use the Customization ommand and let Ema s
do the work for them.
Another ustom-set-... fun tion is ustom-set-fa es. This fun tion
sets the various font fa es. Over time, I have set a onsiderable number
of fa es. Some of the time, I re-set them using ustomize; other times, I
simply edit the ustom-set-fa es expression in my `.ema s' le itself.
The se ond way to ustomize your text-mode-hook is to set it yourself
in your `.ema s' le using ode that has nothing to do with the ustom-
set-... fun tions.
When you do this, and later use ustomize, you will see a message that
says
this option has been hanged outside the ustomize buffer.
This message is only a warning. If you li k on the button to
Save for Future Sessions
Ema s will write a ustom-set-... expression near the end of your `.ema s'
le that will be evaluated after your hand-written expression. It will, there-
fore, overrule your hand-written expression. No harm will be done. When
you do this, however, be areful to remember whi h expression is a tive; if
you forget, you may onfuse yourself.
So long as you remember where the values are set, you will have no
trouble. In any event, the values are always set in your initialization le,
whi h is usually alled `.ema s'.
I myself use ustomize for hardly anything. Mostly, I write expressions
myself.

16.3 Beginning a `.ema s' File


When you start Ema s, it loads your `.ema s' le unless you tell it not
to by spe ifying `-q' on the ommand line. (The ema s -q ommand gives
you a plain, out-of-the-box Ema s.)
A `.ema s' le ontains Lisp expressions. Often, these are no more than
expressions to set values; sometimes they are fun tion de nitions.
See se tion \The Init File `~/.ema s'" in The GNU Ema s Manual, for
a short des ription of initialization les.
This hapter goes over some of the same ground, but is a walk among
extra ts from a omplete, long-used `.ema s' le|my own.
The rst part of the le onsists of omments: reminders to myself. By
now, of ourse, I remember these things, but when I started, I did not.
Text and Auto Fill Mode 217

;;;; Bob's .ema s file


; Robert J. Chassell
; 26 September 1985
Look at that date! I started this le a long time ago. I have been adding to
it ever sin e.
; Ea h se tion in this file is introdu ed by a
; line beginning with four semi olons; and ea h
; entry is introdu ed by a line beginning with
; three semi olons.
This des ribes the usual onventions for omments in Ema s Lisp. Every-
thing on a line that follows a semi olon is a omment. Two, three, and
four semi olons are used as se tion and subse tion markers. (See se tion
\Comments" in The GNU Ema s Lisp Referen e Manual, for more about
omments.)
;;;; The Help Key
; Control-h is the help key;
; after typing ontrol-h, type a letter to
; indi ate the subje t about whi h you want help.
; For an explanation of the help fa ility,
; type ontrol-h two times in a row.
Just remember: type C-h two times for help.
; To find out about any mode, type ontrol-h m
; while in that mode. For example, to find out
; about mail mode, enter mail mode and then type
; ontrol-h m.
`Mode help', as I all this, is very helpful. Usually, it tells you all you need
to know.
Of ourse, you don't need to in lude omments like these in your `.ema s'
le. I in luded them in mine be ause I kept forgetting about Mode help or
the onventions for omments|but I was able to remember to look here to
remind myself.

16.4 Text and Auto Fill Mode


Now we ome to the part that `turns on' Text mode and Auto Fill mode.
;;; Text mode and Auto Fill mode
; The next three lines put Ema s into Text mode
; and Auto Fill mode, and are for writers who
; want to start writing prose rather than ode.

(setq default-major-mode 'text-mode)


(add-hook 'text-mode-hook 'text-mode-hook-identify)
(add-hook 'text-mode-hook 'turn-on-auto-fill)
218 Chapter 16: Your `.ema s' File

Here is the rst part of this `.ema s' le that does something besides
remind a forgetful human!
The rst of the two lines in parentheses tells Ema s to turn on Text mode
when you nd a le, unless that le should go into some other mode, su h
as C mode.
When Ema s reads a le, it looks at the extension to the le name, if
any. (The extension is the part that omes after a `.'.) If the le ends with
a `. ' or `.h' extension then Ema s turns on C mode. Also, Ema s looks at
rst nonblank line of the le; if the line says `-*- C -*-', Ema s turns on
C mode. Ema s possesses a list of extensions and spe i ations that it uses
automati ally. In addition, Ema s looks near the last page for a per-bu er,
\lo al variables list", if any.
See se tions \How Major Modes are Chosen" and \Lo al Variables in
Files" in The GNU Ema s Manual.
Now, ba k to the `.ema s' le.
Here is the line again; how does it work?
(setq default-major-mode 'text-mode)
This line is a short, but omplete Ema s Lisp expression.
We are already familiar with setq. It sets the following variable,
default-major-mode, to the subsequent value, whi h is text-mode. The
single quote mark before text-mode tells Ema s to deal dire tly with the
text-mode variable, not with whatever it might stand for. See Se tion 1.9,
\Setting the Value of a Variable", page 17, for a reminder of how setq works.
The main point is that there is no di eren e between the pro edure you use
to set a value in your `.ema s' le and the pro edure you use anywhere else
in Ema s.
Here are the next two lines:
(add-hook 'text-mode-hook 'text-mode-hook-identify)
(add-hook 'text-mode-hook 'turn-on-auto-fill)
In these two lines, the add-hook ommand rst adds text-mode-hook-
identify to the variable alled text-mode-hook and then adds turn-on-
auto-fill to the variable.
turn-on-auto-fill is the name of a program, that, you guessed it!,
turns on Auto Fill mode. text-mode-hook-identify is a fun tion that
tells toggle-text-mode-auto-fill whi h bu ers are in Text mode.
Every time Ema s turns on Text mode, Ema s runs the ommands
`hooked' onto Text mode. So every time Ema s turns on Text mode, Ema s
also turns on Auto Fill mode.
In brief, the rst line auses Ema s to enter Text mode when you edit
a le, unless the le name extension, rst non-blank line, or lo al variables
tell Ema s otherwise.
Text mode among other a tions, sets the syntax table to work onve-
niently for writers. In Text mode, Ema s onsiders an apostrophe as part
Indent Tabs Mode 219

of a word like a letter; but Ema s does not onsider a period or a spa e as
part of a word. Thus, M-f moves you over `it's'. On the other hand, in C
mode, M-f stops just after the `t' of `it's'.
The se ond and third lines auses Ema s to turn on Auto Fill mode when
it turns on Text mode. In Auto Fill mode, Ema s automati ally breaks a
line that is too wide and brings the ex essively wide part of the line down
to the next line. Ema s breaks lines between words, not within them.
When Auto Fill mode is turned o , lines ontinue to the right as you
type them. Depending on how you set the value of trun ate-lines, the
words you type either disappear o the right side of the s reen, or else are
shown, in a rather ugly and unreadable manner, as a ontinuation line on
the s reen.
In addition, in this part of my `.ema s' le, I tell the Ema s ll ommands
to insert two spa es after a olon:
(setq olon-double-spa e t)

16.5 Mail Aliases


Here is a setq that `turns on' mail aliases, along with more reminders.
;;; Mail mode
; To enter mail mode, type `C-x m'
; To enter RMAIL (for reading mail),
; type `M-x rmail'

(setq mail-aliases t)
This setq ommand sets the value of the variable mail-aliases to t. Sin e
t means true, the line says, in e e t, \Yes, use mail aliases."
Mail aliases are onvenient short names for long email addresses or for
lists of email addresses. The le where you keep your `aliases' is `~/.mailr '.
You write an alias like this:
alias geo georgefoobar.wiz.edu
When you write a message to George, address it to `geo'; the mailer will
automati ally expand `geo' to the full address.

16.6 Indent Tabs Mode


By default, Ema s inserts tabs in pla e of multiple spa es when it formats
a region. (For example, you might indent many lines of text all at on e
with the indent-region ommand.) Tabs look ne on a terminal or with
ordinary printing, but they produ e badly indented output when you use
TEX or Texinfo sin e TEX ignores tabs.
220 Chapter 16: Your `.ema s' File

The following turns o Indent Tabs mode:


;;; Prevent Extraneous Tabs
(setq-default indent-tabs-mode nil)
Note that this line uses setq-default rather than the setq ommand
that we have seen before. The setq-default ommand sets values only in
bu ers that do not have their own lo al values for the variable.
See se tions \Tabs vs. Spa es" and \Lo al Variables in Files" in The
GNU Ema s Manual.

16.7 Some Keybindings


Now for some personal keybindings:
;;; Compare windows
(global-set-key "\C- w" ' ompare-windows)
ompare-windows is a nifty ommand that ompares the text in your
urrent window with text in the next window. It makes the omparison by
starting at point in ea h window, moving over text in ea h window as far as
they mat h. I use this ommand all the time.
This also shows how to set a key globally, for all modes.
The ommand is global-set-key. It is followed by the keybinding. In a
`.ema s' le, the keybinding is written as shown: \C- stands for ` ontrol-
', whi h means `press the ontrol key and the key at the same time'.
The w means `press the w key'. The keybinding is surrounded by double
quotation marks. In do umentation, you would write this as C- w. (If you
were binding a hMETAi key, su h as M- , rather than a hCTLi key, you would
write \M- . See se tion \Rebinding Keys in Your Init File" in The GNU
Ema s Manual, for details.)
The ommand invoked by the keys is ompare-windows. Note that
ompare-windows is pre eded by a single quote; otherwise, Ema s would
rst try to evaluate the symbol to determine its value.
These three things, the double quotation marks, the ba kslash before the
`C', and the single quote mark are ne essary parts of keybinding that I tend
to forget. Fortunately, I have ome to remember that I should look at my
existing `.ema s' le, and adapt what is there.
As for the keybinding itself: C- w. This ombines the pre x key, C- ,
with a single hara ter, in this ase, w. This set of keys, C- followed by a
single hara ter, is stri tly reserved for individuals' own use. (I all these
`own' keys, sin e these are for my own use.) You should always be able to
reate su h a keybinding for your own use without stomping on someone
else's keybinding. If you ever write an extension to Ema s, please avoid
taking any of these keys for publi use. Create a key like C- C-w instead.
Otherwise, we will run out of `own' keys.
Keymaps 221

Here is another keybinding, with a omment:


;;; Keybinding for `o ur'
; I use o ur a lot, so let's bind it to a key:
(global-set-key "\C- o" 'o ur)
The o ur ommand shows all the lines in the urrent bu er that ontain
a mat h for a regular expression. Mat hing lines are shown in a bu er alled
`*O ur*'. That bu er serves as a menu to jump to o urren es.
Here is how to unbind a key, so it does not work:
;;; Unbind `C-x f'
(global-unset-key "\C-xf")
There is a reason for this unbinding: I found I inadvertently typed C-x f
when I meant to type C-x C-f. Rather than nd a le, as I intended, I
a identally set the width for lled text, almost always to a width I did not
want. Sin e I hardly ever reset my default width, I simply unbound the key.
The following rebinds an existing key:
;;; Rebind `C-x C-b' for `buffer-menu'
(global-set-key "\C-x\C-b" 'buffer-menu)
By default, C-x C-b runs the list-buffers ommand. This ommand
lists your bu ers in another window. Sin e I almost always want to do
something in that window, I prefer the buffer-menu ommand, whi h not
only lists the bu ers, but moves point into that window.

16.8 Keymaps
Ema s uses keymaps to re ord whi h keys all whi h ommands. When
you use global-set-key to set the keybinding for a single ommand in all
parts of Ema s, you are spe ifying the keybinding in urrent-global-map.
Spe i modes, su h as C mode or Text mode, have their own keymaps;
the mode-spe i keymaps override the global map that is shared by all
bu ers.
The global-set-key fun tion binds, or rebinds, the global keymap. For
example, the following binds the key C-x C-b to the fun tion buffer-menu:
(global-set-key "\C-x\C-b" 'buffer-menu)
Mode-spe i keymaps are bound using the define-key fun tion, whi h
takes a spe i keymap as an argument, as well as the key and the ommand.
For example, my `.ema s' le ontains the following expression to bind the
texinfo-insert-group ommand to C- C- g:
(define-key texinfo-mode-map "\C- \C- g" 'texinfo-insert-group)
The texinfo-insert-group fun tion itself is a little extension to Texinfo
mode that inserts `group' into a Texinfo le. I use this ommand all the
time and prefer to type the three strokes C- C- g rather than the six
strokes  g r o u p. (`group' and its mat hing `end group' are ommands
222 Chapter 16: Your `.ema s' File

that keep all en losed text together on one page; many multi-line examples
in this book are surrounded by `group ... end group'.)
Here is the texinfo-insert-group fun tion de nition:
(defun texinfo-insert-group ()
"Insert the string group in a Texinfo buffer."
(intera tive)
(beginning-of-line)
(insert "group\n"))
(Of ourse, I ould have used Abbrev mode to save typing, rather than
write a fun tion to insert a word; but I prefer key strokes onsistent with
other Texinfo mode key bindings.)
You will see numerous define-key expressions in `loaddefs.el' as well
as in the various mode libraries, su h as ` -mode.el' and `lisp-mode.el'.
See se tion \Customizing Key Bindings" in The GNU Ema s Manual,
and se tion \Keymaps" in The GNU Ema s Lisp Referen e Manual, for
more information about keymaps.

16.9 Loading Files


Many people in the GNU Ema s ommunity have written extensions to
Ema s. As time goes by, these extensions are often in luded in new releases.
For example, the Calendar and Diary pa kages are now part of the standard
GNU Ema s.
(Cal , whi h I onsider a vital part of Ema s, would be part of the stan-
dard distribution ex ept that it was so large it was pa kaged separately and
no one has hanged that.)
You an use a load ommand to evaluate a omplete le and thereby
install all the fun tions and variables in the le into Ema s. For example:
(load "~/ema s/slowsplit")
This evaluates, i.e. loads, the `slowsplit.el' le or if it exists, the
faster, byte ompiled `slowsplit.el ' le from the `ema s' sub-dire tory of
your home dire tory. The le ontains the fun tion split-window-quietly,
whi h John Robinson wrote in 1989.
The split-window-quietly fun tion splits a window with the minimum
of redisplay. I installed it in 1989 be ause it worked well with the slow 1200
baud terminals I was then using. Nowadays, I only o asionally ome a ross
su h a slow onne tion, but I ontinue to use the fun tion be ause I like the
way it leaves the bottom half of a bu er in the lower of the new windows
and the top half in the upper window.
Autoloading 223

To repla e the key binding for the default split-window-verti ally,


you must also unset that key and bind the keys to split-window-quietly,
like this:
(global-unset-key "\C-x2")
(global-set-key "\C-x2" 'split-window-quietly)
If you load many extensions, as I do, then instead of spe ifying the exa t
lo ation of the extension le, as shown above, you an spe ify that dire tory
as part of Ema s' load-path. Then, when Ema s loads a le, it will sear h
that dire tory as well as its default list of dire tories. (The default list is
spe i ed in `paths.h' when Ema s is built.)
The following ommand adds your `~/ema s' dire tory to the existing
load path:
;;; Ema s Load Path
(setq load-path ( ons "~/ema s" load-path))
In identally, load-library is an intera tive interfa e to the load fun -
tion. The omplete fun tion looks like this:
(defun load-library (library)
"Load the library named LIBRARY.
This is an interfa e to the fun tion `load'."
(intera tive "sLoad library: ")
(load library))
The name of the fun tion, load-library, omes from the use of `library'
as a onventional synonym for ` le'. The sour e for the load-library om-
mand is in the `files.el' library.
Another intera tive ommand that does a slightly di erent job is load-
file. See se tion \Libraries of Lisp Code for Ema s" in The GNU Ema s
Manual, for information on the distin tion between load-library and this
ommand.

16.10 Autoloading
Instead of installing a fun tion by loading the le that ontains it, or by
evaluating the fun tion de nition, you an make the fun tion available but
not a tually install it until it is rst alled. This is alled autoloading.
When you exe ute an autoloaded fun tion, Ema s automati ally evalu-
ates the le that ontains the de nition, and then alls the fun tion.
Ema s starts qui ker with autoloaded fun tions, sin e their libraries are
not loaded right away; but you need to wait a moment when you rst use
su h a fun tion, while its ontaining le is evaluated.
Rarely used fun tions are frequently autoloaded. The `loaddefs.el' li-
brary ontains hundreds of autoloaded fun tions, from bookmark-set to
wordstar-mode. Of ourse, you may ome to use a `rare' fun tion frequently.
224 Chapter 16: Your `.ema s' File

When you do, you should load that fun tion's le with a load expression in
your `.ema s' le.
In my `.ema s' le for Ema s version 21, I load 12 libraries that ontain
fun tions that would otherwise be autoloaded. (A tually, it would have been
better to in lude these les in my `dumped' Ema s when I built it, but I
forgot. See se tion \Building Ema s" in The GNU Ema s Lisp Referen e
Manual, and the `INSTALL' le for more about dumping.)
You may also want to in lude autoloaded expressions in your `.ema s'
le. autoload is a built-in fun tion that takes up to ve arguments, the nal
three of whi h are optional. The rst argument is the name of the fun tion
to be autoloaded; the se ond is the name of the le to be loaded. The third
argument is do umentation for the fun tion, and the fourth tells whether
the fun tion an be alled intera tively. The fth argument tells what type
of obje t|autoload an handle a keymap or ma ro as well as a fun tion
(the default is a fun tion).
Here is a typi al example:
(autoload 'html-helper-mode
"html-helper-mode" "Edit HTML do uments" t)

(html-helper-mode is an alternative to html-mode, whi h is a standard part


of the distribution).
This expression autoloads the html-helper-mode fun tion. It takes
it from the `html-helper-mode.el' le (or from the byte ompiled
le `html-helper-mode.el ', if it exists.) The le must be lo ated
in a dire tory spe i ed by load-path. The do umentation says that
this is a mode to help you edit do uments written in the HyperText
Markup Language. You an all this mode intera tively by typing
M-x html-helper-mode. (You need to dupli ate the fun tion's regular
do umentation in the autoload expression be ause the regular fun tion is
not yet loaded, so its do umentation is not available.)
See se tion \Autoload" in The GNU Ema s Lisp Referen e Manual, for
more information.

16.11 A Simple Extension: line-to-top-of-window


Here is a simple extension to Ema s that moves the line point is on to
the top of the window. I use this all the time, to make text easier to read.
You an put the following ode into a separate le and then load it from
your `.ema s' le, or you an in lude it within your `.ema s' le.
A Simple Extension: line-to-top-of-window 225

Here is the de nition:


;;; Line to top of window;
;;; repla e three keystroke sequen e C-u 0 C-l
(defun line-to-top-of-window ()
"Move the line point is on to top of window."
(intera tive)
(re enter 0))
Now for the keybinding.
Nowadays, fun tion keys as well as mouse button events and non-as ii
hara ters are written within square bra kets, without quotation marks. (In
Ema s version 18 and before, you had to write di erent fun tion key bindings
for ea h di erent make of terminal.)
I bind line-to-top-of-window to my hF6i fun tion key like this:
(global-set-key [f6℄ 'line-to-top-of-window)
For more information, see se tion \Rebinding Keys in Your Init File" in
The GNU Ema s Manual.
If you run two versions of GNU Ema s, su h as versions 20 and 21, and
use one `.ema s' le, you an sele t whi h ode to evaluate with the following
onditional:
( ond
((string-equal (number-to-string 20) (substring (ema s-version) 10 12))
;; evaluate version 20 ode
( ... ))
((string-equal (number-to-string 21) (substring (ema s-version) 10 12))
;; evaluate version 21 ode
( ... )))
For example, in ontrast to version 20, version 21 blinks its ursor by
default. I hate su h blinking, as well as some other features in version 21,
so I pla ed the following in my `.ema s' le2:
(if (string-equal "21" (substring (ema s-version) 10 12))
(progn
(blink- ursor-mode 0)
;; Insert newline when you press `C-n' (next-line)
;; at the end of the buffer
(setq next-line-add-newlines t)
;; Turn on image viewing
(auto-image-file-mode t)

2 When I start instan es of Ema s that do not load my `.ema s' le or any site le, I
also turn o blinking:
ema s -q --no-site-file -eval '(blink- ursor-mode nil)'
226 Chapter 16: Your `.ema s' File

;; Turn on menu bar (this bar has text)


;; (Use numeri argument to turn on)
(menu-bar-mode 1)
;; Turn off tool bar (this bar has i ons)
;; (Use numeri argument to turn on)
(tool-bar-mode nil)
;; Turn off tooltip mode for tool bar
;; (This mode auses i on explanations to pop up)
;; (Use numeri argument to turn on)
(tooltip-mode nil)
;; If tooltips turned on, make tips appear promptly
(setq tooltip-delay 0.1) ; default is one se ond
))
(You will note that instead of typing (number-to-string 21), I de ided to
save typing and wrote `21' as a string, "21", rather than onvert it from
an integer to a string. In this instan e, this expression is better than the
longer, but more general (number-to-string 21). However, if you do not
know ahead of time what type of information will be returned, then the
number-to-string fun tion will be needed.)

16.12 X11 Colors


You an spe ify olors when you use Ema s with the MIT X Windowing
system.
I dislike the default olors and spe ify my own.
Here are the expressions in my `.ema s' le that set values:
;; Set ursor olor
(set- ursor- olor "white")

;; Set mouse olor


(set-mouse- olor "white")

;; Set foreground and ba kground


(set-foreground- olor "white")
(set-ba kground- olor "darkblue")
;;; Set highlighting olors for isear h and drag
(set-fa e-foreground 'highlight "white")
(set-fa e-ba kground 'highlight "blue")
(set-fa e-foreground 'region " yan")
(set-fa e-ba kground 'region "blue")
(set-fa e-foreground 'se ondary-sele tion "skyblue")
(set-fa e-ba kground 'se ondary-sele tion "darkblue")
A Modi ed Mode Line 227

;; Set alendar highlighting olors


(setq alendar-load-hook
'(lambda ()
(set-fa e-foreground 'diary-fa e "skyblue")
(set-fa e-ba kground 'holiday-fa e "slate blue")
(set-fa e-foreground 'holiday-fa e "white")))
The various shades of blue soothe my eye and prevent me from seeing the
s reen i ker.
Alternatively, I ould have set my spe i ations in various X initialization
les. For example, I ould set the foreground, ba kground, ursor, and
pointer (i.e., mouse) olors in my `~/.Xresour es' le like this:
Ema s*foreground: white
Ema s*ba kground: darkblue
Ema s* ursorColor: white
Ema s*pointerColor: white
In any event, sin e it is not part of Ema s, I set the root olor of my X
window in my `~/.xinitr ' le, like this3:
# I use TWM for window manager.
xsetroot -solid Navy -fg white &

16.13 Mis ellaneous Settings for a `.ema s' File


Here are a few mis ellaneous settings:
Set the shape and olor of the mouse ursor:
; Cursor shapes are defined in
; `/usr/in lude/X11/ ursorfont.h';
; for example, the `target' ursor is number 128;
; the `top_left_arrow' ursor is number 132.
(let ((mpointer (x-get-resour e "*mpointer"
"*ema s*mpointer")))
;; If you have not set your mouse pointer
;; then set it, otherwise leave as is:
(if (eq mpointer nil)
(setq mpointer "132")) ; top_left_arrow
(setq x-pointer-shape (string-to-int mpointer))
(set-mouse- olor "white"))

3 I o asionally run more modern window managers, su h as Saw sh with GNOME,


Enlightenment, SCWM, or KDE; in those ases, I often spe ify an image rather than
a plain olor.
228 Chapter 16: Your `.ema s' File

16.14 A Modi ed Mode Line

Finally, a feature I really like: a modi ed mode line.

When I work over a network, I forget whi h ma hine I am using. Also, I


tend to I lose tra k of where I am, and whi h line point is on.

So I reset my mode line to look like this:

-:-- foo.texi rattlesnake:/home/bob/ Line 1 (Texinfo Fill) Top

I am visiting a le alled `foo.texi', on my ma hine `rattlesnake' in


my `/home/bob' bu er. I am on line 1, in Texinfo mode, and am at the top
of the bu er.

My `.ema s' le has a se tion that looks like this:

;; Set a Mode Line that tells me whi h ma hine, whi h dire tory,
;; and whi h line I am on, plus the other ustomary information.
(setq default-mode-line-format
(quote
(#("-" 0 1
(help-e ho
"mouse-1: sele t window, mouse-2: delete others ..."))
mode-line-mule-info
mode-line-modified
mode-line-frame-identifi ation
" "
mode-line-buffer-identifi ation
" "
(:eval (substring
(system-name) 0 (string-mat h "\\..+" (system-name))))
":"
default-dire tory
#(" " 0 1
(help-e ho
"mouse-1: sele t window, mouse-2: delete others ..."))
(line-number-mode " Line %l ")
global-mode-string
A Modi ed Mode Line 229

#(" %[(" 0 6
(help-e ho
"mouse-1: sele t window, mouse-2: delete others ..."))
(:eval (mode-line-mode-name))
mode-line-pro ess
minor-mode-alist
#("%n" 0 2 (help-e ho "mouse-2: widen" lo al-map (keymap ...)))
")%℄ "
(-3 . "%P")
;; "-%-"
)))
Here, I rede ne the default mode line. Most of the parts are from the original;
but I make a few hanges. I set the default mode line format so as to permit
various modes, su h as Info, to override it.
Many elements in the list are self-explanatory: mode-line-modified is
a variable that tells whether the bu er has been modi ed, mode-name tells
the name of the mode, and so on. However, the format looks ompli ated
be ause of two features we have not dis ussed.
The rst string in the mode line is a dash or hyphen, `-'. In the old days,
it would have been spe i ed simply as "-". But nowadays, Ema s an add
properties to a string, su h as highlighting or, as in this ase, a help feature.
If you pla e your mouse ursor over the hyphen, some help information ap-
pears (By default, you must wait one se ond before the information appears.
You an hange that timing by hanging the value of tooltip-delay.)
The new string format has a spe ial syntax:
#("-" 0 1 (help-e ho "mouse-1: sele t window, ..."))
The #( begins a list. The rst element of the list is the string itself, just one
`-'. The se ond and third elements spe ify the range over whi h the fourth
element applies. A range starts after a hara ter, so a zero means the range
starts just before the rst hara ter; a 1 means that the range ends just
after the rst hara ter. The third element is the property for the range.
It onsists of a property list, a property name, in this ase, `help-e ho',
followed by a value, in this ase, a string. The se ond, third, and fourth
elements of this new string format an be repeated.
See se tion \Text Properties in String" in The GNU Ema s Lisp Refer-
en e Manual, and see se tion \Mode Line Format" in The GNU Ema s Lisp
Referen e Manual, for more information.
mode-line-buffer-identifi ation displays the urrent bu er name.
It is a list beginning (#("%12b" 0 4 .... The #( begins the list.
The `"%12b"' displays the urrent bu er name, using the buffer-name
fun tion with whi h we are familiar; the `12' spe i es the maximum number
of hara ters that will be displayed. When a name has fewer hara ters,
whitespa e is added to ll out to this number. (Bu er names an and often
230 Chapter 16: Your `.ema s' File

should be longer than 12 hara ters; this length works well in a typi al 80
olumn wide window.)
:eval is a new feature in GNU Ema s version 21. It says to evaluate
the following form and use the result as a string to display. In this ase, the
expression displays the rst omponent of the full system name. The end of
the rst omponent is a `.' (`period'), so I use the string-mat h fun tion
to tell me the length of the rst omponent. The substring from the zeroth
hara ter to that length is the name of the ma hine.
This is the expression:
(:eval (substring
(system-name) 0 (string-mat h "\\..+" (system-name))))
`%[' and `%℄' ause a pair of square bra kets to appear for ea h re ursive
editing level. `%n' says `Narrow' when narrowing is in e e t. `%P' tells you
the per entage of the bu er that is above the bottom of the window, or
`Top', `Bottom', or `All'. (A lower ase `p' tell you the per entage above the
top of the window.) `%-' inserts enough dashes to ll out the line.
Remember, \You don't have to like Ema s to like it" | your own Ema s
an have di erent olors, di erent ommands, and di erent keys than a
default Ema s.
On the other hand, if you want to bring up a plain `out of the box' Ema s,
with no ustomization, type:
ema s -q
This will start an Ema s that does not load your `~/.ema s' initialization
le. A plain, default Ema s. Nothing more.
debug 231

17 Debugging
GNU Ema s has two debuggers, debug and edebug. The rst is built
into the internals of Ema s and is always with you; the se ond requires that
you instrument a fun tion before you an use it.
Both debuggers are des ribed extensively in se tion \Debugging Lisp Pro-
grams" in The GNU Ema s Lisp Referen e Manual. In this hapter, I will
walk through a short example of ea h.

17.1 debug
Suppose you have written a fun tion de nition that is intended to return
the sum of the numbers 1 through a given number. (This is the triangle
fun tion dis ussed earlier. See \Example with De rementing Counter",
page 129, for a dis ussion.)
However, your fun tion de nition has a bug. You have mistyped `1=' for
`1-'. Here is the broken de nition:
(defun triangle-bugged (number)
"Return sum of numbers 1 through NUMBER in lusive."
(let ((total 0))
(while (> number 0)
(setq total (+ total number))
(setq number (1= number))) ; Error here.
total))
If you are reading this in Info, you an evaluate this de nition in the
normal fashion. You will see triangle-bugged appear in the e ho area.
Now evaluate the triangle-bugged fun tion with an argument of 4:
(triangle-bugged 4)
In GNU Ema s version 21, you will reate and enter a `*Ba ktra e*' bu er
that says:
---------- Buffer: *Ba ktra e* ----------
Debugger entered--Lisp error: (void-fun tion 1=)
(1= number)
(setq number (1= number))
(while (> number 0) (setq total (+ total number))
(setq number (1= number)))
(let ((total 0)) (while (> number 0) (setq total ...)
(setq number ...)) total)
triangle-bugged(4)
232 Chapter 17: Debugging

eval((triangle-bugged 4))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
all-intera tively(eval-last-sexp)
---------- Buffer: *Ba ktra e* ----------
(I have reformatted this example slightly; the debugger does not fold long
lines. As usual, you an quit the debugger by typing q in the `*Ba ktra e*'
bu er.)
In pra ti e, for a bug as simple as this, the `Lisp error' line will tell you
what you need to know to orre t the de nition. The fun tion 1= is `void'.
In GNU Ema s 20 and before, you will see:
Symbol's fun tion definition is void: 1=
whi h has the same meaning as the `*Ba ktra e*' bu er line in version 21.
However, suppose you are not quite ertain what is going on? You an
read the omplete ba ktra e.
In this ase, you need to run GNU Ema s 21, whi h automati ally starts
the debugger that puts you in the `*Ba ktra e*' bu er; or else, you need to
start the debugger manually as des ribed below.
Read the `*Ba ktra e*' bu er from the bottom up; it tells you what
Ema s did that led to the error. Ema s made an intera tive all to C-x C-
e (eval-last-sexp), whi h led to the evaluation of the triangle-bugged
expression. Ea h line above tells you what the Lisp interpreter evaluated
next.
The third line from the top of the bu er is
(setq number (1= number))
Ema s tried to evaluate this expression; in order to do so, it tried to evaluate
the inner expression shown on the se ond line from the top:
(1= number)
This is where the error o urred; as the top line says:
Debugger entered--Lisp error: (void-fun tion 1=)
You an orre t the mistake, re-evaluate the fun tion de nition, and then
run your test again.

17.2 debug-on-entry
GNU Ema s 21 starts the debugger automati ally when your fun tion
has an error. GNU Ema s version 20 and before did not; it simply presented
you with an error message. You had to start the debugger manually.
You an start the debugger manually for all versions of Ema s; the ad-
vantage is that the debugger runs even if you do not have a bug in your
ode. Sometimes your ode will be free of bugs!
debug-on-entry 233

You an enter the debugger when you all the fun tion by alling debug-
on-entry.
Type:
M-x debug-on-entry RET triangle-bugged RET
Now, evaluate the following:
(triangle-bugged 5)
All versions of Ema s will reate a `*Ba ktra e*' bu er and tell you that it
is beginning to evaluate the triangle-bugged fun tion:
---------- Buffer: *Ba ktra e* ----------
Debugger entered--entering a fun tion:
* triangle-bugged(5)
eval((triangle-bugged 5))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
all-intera tively(eval-last-sexp)
---------- Buffer: *Ba ktra e* ----------
In the `*Ba ktra e*' bu er, type d. Ema s will evaluate the rst expres-
sion in triangle-bugged; the bu er will look like this:
---------- Buffer: *Ba ktra e* ----------
Debugger entered--beginning evaluation of fun tion all form:
* (let ((total 0)) (while (> number 0) (setq total ...)
(setq number ...)) total)
* triangle-bugged(5)
eval((triangle-bugged 5))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
all-intera tively(eval-last-sexp)
---------- Buffer: *Ba ktra e* ----------
Now, type d again, eight times, slowly. Ea h time you type d, Ema s will
evaluate another expression in the fun tion de nition.
234 Chapter 17: Debugging

Eventually, the bu er will look like this:


---------- Buffer: *Ba ktra e* ----------
Debugger entered--beginning evaluation of fun tion all form:
* (setq number (1= number))
* (while (> number 0) (setq total (+ total number))
(setq number (1= number)))
* (let ((total 0)) (while (> number 0) (setq total ...)
(setq number ...)) total)
* triangle-bugged(5)
eval((triangle-bugged 5))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
all-intera tively(eval-last-sexp)
---------- Buffer: *Ba ktra e* ----------

Finally, after you type d two more times, Ema s will rea h the error, and
the top two lines of the `*Ba ktra e*' bu er will look like this:
---------- Buffer: *Ba ktra e* ----------
Debugger entered--Lisp error: (void-fun tion 1=)
* (1= number)
...
---------- Buffer: *Ba ktra e* ----------

By typing d, you were able to step through the fun tion.


You an quit a `*Ba ktra e*' bu er by typing q in it; this quits the tra e,
but does not an el debug-on-entry.
To an el the e e t of debug-on-entry, all an el-debug-on-entry
and the name of the fun tion, like this:
M-x an el-debug-on-entry RET triangle-bugged RET

(If you are reading this in Info, an el debug-on-entry now.)

17.3 debug-on-quit and (debug)


In addition to setting debug-on-error or alling debug-on-entry, there
are two other ways to start debug.
You an start debug whenever you type C-g (keyboard-quit) by setting
the variable debug-on-quit to t. This is useful for debugging in nite loops.
The edebug Sour e Level Debugger 235

Or, you an insert a line that says (debug) into your ode where you
want the debugger to start, like this:
(defun triangle-bugged (number)
"Return sum of numbers 1 through NUMBER in lusive."
(let ((total 0))
(while (> number 0)
(setq total (+ total number))
(debug) ; Start debugger.
(setq number (1= number))) ; Error here.
total))

The debug fun tion is des ribed in detail in se tion \The Lisp Debugger"
in The GNU Ema s Lisp Referen e Manual.

17.4 The edebug Sour e Level Debugger


Edebug is a sour e level debugger. Edebug normally displays the sour e
of the ode you are debugging, with an arrow at the left that shows whi h
line you are urrently exe uting.
You an walk through the exe ution of a fun tion, line by line, or run
qui kly until rea hing a breakpoint where exe ution stops.
Edebug is des ribed in se tion \Edebug" in The GNU Ema s Lisp Ref-
eren e Manual.
Here is a bugged fun tion de nition for triangle-re ursively. See
Se tion 11.3.4, \Re ursion in pla e of a ounter", page 137, for a review of
it.
(defun triangle-re ursively-bugged (number)
"Return sum of numbers 1 through NUMBER in lusive.
Uses re ursion."
(if (= number 1)
1
(+ number
(triangle-re ursively-bugged
(1= number))))) ; Error here.

Normally, you would install this de nition by positioning your ursor after
the fun tion's losing parenthesis and typing C-x C-e (eval-last-sexp) or
else by positioning your ursor within the de nition and typing C-M-x (eval-
defun). (By default, the eval-defun ommand works only in Ema s Lisp
mode or in Lisp Intera tive mode.)
236 Chapter 17: Debugging

However, to prepare this fun tion de nition for Edebug, you must rst
instrument the ode using a di erent ommand. You an do this by posi-
tioning your ursor within the de nition and typing
M-x edebug-defun RET
This will ause Ema s to load Edebug automati ally if it is not already
loaded, and properly instrument the fun tion.
After instrumenting the fun tion, pla e your ursor after the following
expression and type C-x C-e (eval-last-sexp):
(triangle-re ursively-bugged 3)
You will be jumped ba k to the sour e for triangle-re ursively-bugged
and the ursor positioned at the beginning of the if line of the fun tion.
Also, you will see an arrowhead at the left hand side of that line. The
arrowhead marks the line where the fun tion is exe uting. (In the following
examples, we show the arrowhead with `=>'; in a windowing system, you
may see the arrowhead as a solid triangle in the window `fringe'.)
=>?(if (= number 1)
In the example, the lo ation of point is displayed with a star, `?' (in Info, it
is displayed as `-!-').
If you now press hSPCi, point will move to the next expression to be
exe uted; the line will look like this:
=>(if ?(= number 1)
As you ontinue to press hSPCi, point will move from expression to expression.
At the same time, whenever an expression returns a value, that value will be
displayed in the e ho area. For example, after you move point past number,
you will see the following:
Result: 3 = C-
This means the value of number is 3, whi h is as ii ` ontrol- ' (the third
letter of the alphabet).
You an ontinue moving through the ode until you rea h the line with
the error. Before evaluation, that line looks like this:
=> ?(1= number))))) ; Error here.
When you press hSPCi on e again, you will produ e an error message that
says:
Symbol's fun tion definition is void: 1=
This is the bug.
Press q to quit Edebug.
To remove instrumentation from a fun tion de nition, simply re-evaluate
it with a ommand that does not instrument it. For example, you ould
pla e your ursor after the de nition's losing parenthesis and type C-x C-e.
Edebug does a great deal more than walk with you through a fun tion.
You an set it so it ra es through on its own, stopping only at an error or at
spe i ed stopping points; you an ause it to display the hanging values of
Debugging Exer ises 237

various expressions; you an nd out how many times a fun tion is alled,
and more.
Edebug is des ribed in se tion \Edebug" in The GNU Ema s Lisp Ref-
eren e Manual.

17.5 Debugging Exer ises


 Install the ount-words-region fun tion and then ause it to enter
the built-in debugger when you all it. Run the ommand on a region
ontaining two words. You will need to press d a remarkable number of
times. On your system, is a `hook' alled after the ommand nishes?
(For information on hooks, see se tion \Command Loop Overview" in
The GNU Ema s Lisp Referen e Manual.)
 Copy ount-words-region into the `*s rat h*' bu er, instrument the
fun tion for Edebug, and walk through its exe ution. The fun tion does
not need to have a bug, although you an introdu e one if you wish. If
the fun tion la ks a bug, the walk-through ompletes without problems.
 While running Edebug, type ? to see a list of all the Edebug ommands.
(The global-edebug-prefix is usually C-x X, i.e. hCTLi-x followed by
an upper ase X; use this pre x for ommands made outside of the
Edebug debugging bu er.)
 In the Edebug debugging bu er, use the p (edebug-boun e-point)
ommand to see where in the region the ount-words-region is work-
ing.
 Move point to some spot further down fun tion and then type the h
(edebug-goto-here) ommand to jump to that lo ation.
 Use the t (edebug-tra e-mode) ommand to ause Edebug to walk
through the fun tion on its own; use an upper ase T for edebug-Tra e-
fast-mode.
 Set a breakpoint, then run Edebug in Tra e mode until it rea hes the
stopping point.
238 Chapter 17: Debugging
Con lusion 239

18 Con lusion
We have now rea hed the end of this Introdu tion. You have now learned
enough about programming in Ema s Lisp to set values, to write simple
`.ema s' les for yourself and your friends, and write simple ustomizations
and extensions to Ema s.
This is a pla e to stop. Or, if you wish, you an now go onward, and
tea h yourself.
You have learned some of the basi nuts and bolts of programming. But
only some. There are a great many more bra kets and hinges that are easy
to use that we have not tou hed.
A path you an follow right now lies among the sour es to GNU Ema s
and in The GNU Ema s Lisp Referen e Manual.
The Ema s Lisp sour es are an adventure. When you read the sour es
and ome a ross a fun tion or expression that is unfamiliar, you need to
gure out or nd out what it does.
Go to the Referen e Manual. It is a thorough, omplete, and fairly easy-
to-read des ription of Ema s Lisp. It is written not only for experts, but
for people who know what you know. (The Referen e Manual omes with
the standard GNU Ema s distribution. Like this introdu tion, it omes as
a Texinfo sour e le, so you an read it on-line and as a typeset, printed
book.)
Go to the other on-line help that is part of GNU Ema s: the on-line
do umentation for all fun tions, and find-tags, the program that takes
you to sour es.
Here is an example of how I explore the sour es. Be ause of its name,
`simple.el' is the le I looked at rst, a long time ago. As it happens some
of the fun tions in `simple.el' are ompli ated, or at least look ompli ated
at rst sight. The open-line fun tion, for example, looks ompli ated.
You may want to walk through this fun tion slowly, as we did with
the forward-senten e fun tion. (See Se tion 12.3, \forward-senten e",
page 151.) Or you may want to skip that fun tion and look at another,
su h as split-line. You don't need to read all the fun tions. A ording
to ount-words-in-defun, the split-line fun tion ontains 27 words and
symbols.
Even though it is short, split-line ontains four expressions we have
not studied: skip- hars-forward, indent-to, urrent- olumn and `?\n'.
Consider the skip- hars-forward fun tion. (It is part of the fun tion
de nition for ba k-to-indentation, whi h is shown in Se tion 3.11, \Re-
view", page 46.)
In GNU Ema s, you an nd out more about skip- hars-forward by
typing C-h f (des ribe-fun tion) and the name of the fun tion. This gives
you the fun tion do umentation.
240 Chapter 18: Con lusion

You may be able to guess what is done by a well named fun tion su h as
indent-to; or you an look it up, too. In identally, the des ribe-fun tion
fun tion itself is in `help.el'; it is one of those long, but de ipherable fun -
tions. You an look up des ribe-fun tion using the C-h f ommand!
In this instan e, sin e the ode is Lisp, the `*Help*' bu er ontains the
name of the library ontaining the fun tion's sour e. You an put point over
the name of the library and press the RET key, whi h in this situation is
bound to help-follow, and be taken dire tly to the sour e, in the same way
as M-. (find-tag).
The de nition for des ribe-fun tion illustrates how to ustomize the
intera tive expression without using the standard hara ter odes; and it
shows how to reate a temporary bu er.
(The indent-to fun tion is written in C rather than Ema s Lisp; it is a
`built-in' fun tion. help-follow only provides you with the do umentation
of a built-in fun tion; it does not take you to the sour e. But find-tag will
take you to the sour e, if properly set up.)
You an look at a fun tion's sour e using find-tag, whi h is bound to
M-. Finally, you an nd out what the Referen e Manual has to say by
visiting the manual in Info, and typing i (Info-index) and the name of the
fun tion, or by looking up skip- hars-forward in the index to a printed
opy of the manual.
Similarly, you an nd out what is meant by `?\n'. You an try using
Info-index with `?\n'. It turns out that this a tion won't help; but don't
give up. If you sear h the index for `\n' without the `?', you will be taken
dire tly to the relevant se tion of the manual. (See se tion \Chara ter Type"
in The GNU Ema s Lisp Referen e Manual. `?\n' stands for the newline
hara ter.)
Other interesting sour e les in lude `paragraphs.el', `loaddefs.el',
and `loadup.el'. The `paragraphs.el' le in ludes short, easily understood
fun tions as well as longer ones. The `loaddefs.el' le ontains the many
standard autoloads and many keymaps. I have never looked at it all; only at
parts. `loadup.el' is the le that loads the standard parts of Ema s; it tells
you a great deal about how Ema s is built. (See se tion \Building Ema s"
in The GNU Ema s Lisp Referen e Manual, for more about building.)
As I said, you have learned some nuts and bolts; however, and very
importantly, we have hardly tou hed major aspe ts of programming; I have
said nothing about how to sort information, ex ept to use the prede ned
sort fun tion; I have said nothing about how to store information, ex ept
to use variables and lists; I have said nothing about how to write programs
that write programs. These are topi s for another, and di erent kind of
book, a di erent kind of learning.
What you have done is learn enough for mu h pra ti al work with GNU
Ema s. What you have done is get started. This is the end of a beginning.
The the-the Fun tion 241

Appendix A The the-the Fun tion


Sometimes when you you write text, you dupli ate words|as with \you
you" near the beginning of this senten e. I nd that most frequently, I
dupli ate \the'; hen e, I all the fun tion for dete ting dupli ated words,
the-the.
As a rst step, you ould use the following regular expression to sear h
for dupli ates:
\\(\\w+[ \t\n℄+\\)\\1
This regexp mat hes one or more word- onstituent hara ters followed by
one or more spa es, tabs, or newlines. However, it does not dete t dupli ated
words on di erent lines, sin e the ending of the rst word, the end of the
line, is di erent from the ending of the se ond word, a spa e. (For more
information about regular expressions, see Chapter 12, \Regular Expression
Sear hes", page 149, as well as se tion \Syntax of Regular Expressions" in
The GNU Ema s Manual, and se tion \Regular Expressions" in The GNU
Ema s Lisp Referen e Manual.)
You might try sear hing just for dupli ated word- onstituent hara ters
but that does not work sin e the pattern dete ts doubles su h as the two
o urren es of `th' in `with the'.
Another possible regexp sear hes for word- onstituent hara ters followed
by non-word- onstituent hara ters, redupli ated. Here, `\\w+' mat hes one
or more word- onstituent hara ters and `\\W*' mat hes zero or more non-
word- onstituent hara ters.
\\(\\(\\w+\\)\\W*\\)\\1
Again, not useful.
Here is the pattern that I use. It is not perfe t, but good enough. `\\b'
mat hes the empty string, provided it is at the beginning or end of a word;
`[^ \n\t℄+' mat hes one or more o urren es of any hara ters that are
not an -sign, spa e, newline, or tab.
\\b\\([^ \n\t℄+\\)[ \n\t℄+\\1\\b
One an write more ompli ated expressions, but I found that this ex-
pression is good enough, so I use it.
Here is the the-the fun tion, as I in lude it in my `.ema s' le, along
with a handy global key binding:
(defun the-the ()
"Sear h forward for for a dupli ated word."
(intera tive)
(message "Sear hing for for dupli ated words ...")
(push-mark)
242 Appendix A: The the-the Fun tion

;; This regexp is not perfe t


;; but is fairly good over all:
(if (re-sear h-forward
"\\b\\([^ \n\t℄+\\)[ \n\t℄+\\1\\b" nil 'move)
(message "Found dupli ated word.")
(message "End of buffer")))
;; Bind `the-the' to C- \
(global-set-key "\C- \\" 'the-the)

Here is test text:


one two two three four five
five six seven
You an substitute the other regular expressions shown above in the fun -
tion de nition and try ea h of them on this list.
The rotate-yank-pointer Fun tion 243

Appendix B Handling the Kill Ring


The kill ring is a list that is transformed into a ring by the workings of the
rotate-yank-pointer fun tion. The yank and yank-pop ommands use the
rotate-yank-pointer fun tion. This appendix des ribes the rotate-yank-
pointer fun tion as well as both the yank and the yank-pop ommands.

B.1 The rotate-yank-pointer Fun tion


The rotate-yank-pointer fun tion hanges the element in the kill ring
to whi h kill-ring-yank-pointer points. For example, it an hange
kill-ring-yank-pointer from pointing to the se ond element to point to
the third element.
Here is the ode for rotate-yank-pointer:
(defun rotate-yank-pointer (arg)
"Rotate the yanking point in the kill ring."
(intera tive "p")
(let ((length (length kill-ring)))
(if (zerop length)
;; then-part
(error "Kill ring is empty")
;; else-part
(setq kill-ring-yank-pointer
(nth dr (% (+ arg
(- length
(length
kill-ring-yank-pointer)))
length)
kill-ring)))))
The rotate-yank-pointer fun tion looks omplex, but as usual, it an
be understood by taking it apart pie e by pie e. First look at it in skeletal
form:
(defun rotate-yank-pointer (arg)
"Rotate the yanking point in the kill ring."
(intera tive "p")
(let varlist
body ...)
This fun tion takes one argument, alled arg. It has a brief do umen-
tation string; and it is intera tive with a small `p', whi h means that the
argument must be a pro essed pre x passed to the fun tion as a number.
The body of the fun tion de nition is a let expression, whi h itself has
a body as well as a varlist.
244 Appendix B: Handling the Kill Ring

The let expression de lares a variable that will be only usable within
the bounds of this fun tion. This variable is alled length and is bound to
a value that is equal to the number of items in the kill ring. This is done
by using the fun tion alled length. (Note that this fun tion has the same
name as the variable alled length; but one use of the word is to name the
fun tion and the other is to name the variable. The two are quite distin t.
Similarly, an English speaker will distinguish between the meanings of the
word `ship' when he says: "I must ship this pa kage immediately." and "I
must get aboard the ship immediately.")
The fun tion length tells the number of items there are in a list, so
(length kill-ring) returns the number of items there are in the kill ring.

B.1.1 The Body of rotate-yank-pointer


The body of rotate-yank-pointer is a let expression and the body of
the let expression is an if expression.
The purpose of the if expression is to nd out whether there is anything
in the kill ring. If the kill ring is empty, the error fun tion stops evaluation
of the fun tion and prints a message in the e ho area. On the other hand, if
the kill ring has something in it, the work of the fun tion is done.
Here is the if-part and then-part of the if expression:
(if (zerop length) ; if-part
(error "Kill ring is empty") ; then-part
...
If there is not anything in the kill ring, its length must be zero and an error
message sent to the user: `Kill ring is empty'. The if expression uses the
fun tion zerop whi h returns true if the value it is testing is zero. When
zerop tests true, the then-part of the if is evaluated. The then-part is
a list starting with the fun tion error, whi h is a fun tion that is similar
to the message fun tion (see Se tion 1.8.5, \message", page 16), in that it
prints a one-line message in the e ho area. However, in addition to printing
a message, error also stops evaluation of the fun tion within whi h it is
embedded. This means that the rest of the fun tion will not be evaluated if
the length of the kill ring is zero.
(In my opinion, it is slightly misleading, at least to humans, to use the
term `error' as the name of the error fun tion. A better term would be
` an el'. Stri tly speaking, of ourse, you annot point to, mu h less rotate
a pointer to a list that has no length, so from the point of view of the
omputer, the word `error' is orre t. But a human expe ts to attempt this
sort of thing, if only to nd out whether the kill ring is full or empty. This
is an a t of exploration.
(From the human point of view, the a t of exploration and dis overy is
not ne essarily an error, and therefore should not be labelled as one, even in
the bowels of a omputer. As it is, the ode in Ema s implies that a human
who is a ting virtuously, by exploring his or her environment, is making an
The else-part of the if expression 245

error. This is bad. Even though the omputer takes the same steps as it
does when there is an `error', a term su h as ` an el' would have a learer
onnotation.)

The else-part of the if expression


The else-part of the if expression is dedi ated to setting the value of
kill-ring-yank-pointer when the kill ring has something in it. The ode
looks like this:
(setq kill-ring-yank-pointer
(nth dr (% (+ arg
(- length
(length kill-ring-yank-pointer)))
length)
kill-ring)))))

This needs some examination. Clearly, kill-ring-yank-pointer is be-


ing set to be equal to some dr of the kill ring, using the nth dr fun tion
that is des ribed in an earlier se tion. (See Se tion 8.5, \ opy-region-as-kill",
page 102.) But exa tly how does it do this?
Before looking at the details of the ode let's rst onsider the purpose
of the rotate-yank-pointer fun tion.
The rotate-yank-pointer fun tion hanges what kill-ring-yank-
pointer points to. If kill-ring-yank-pointer starts by pointing to the
rst element of a list, a all to rotate-yank-pointer auses it to point to
the se ond element; and if kill-ring-yank-pointer points to the se ond
element, a all to rotate-yank-pointer auses it to point to the third ele-
ment. (And if rotate-yank-pointer is given an argument greater than 1,
it jumps the pointer that many elements.)
The rotate-yank-pointer fun tion uses setq to reset what the kill-
ring-yank-pointer points to. If kill-ring-yank-pointer points to the
rst element of the kill ring, then, in the simplest ase, the rotate-yank-
pointer fun tion must ause it to point to the se ond element. Put another
way, kill-ring-yank-pointer must be reset to have a value equal to the
dr of the kill ring.
That is, under these ir umstan es,
(setq kill-ring-yank-pointer
("some text" "a different pie e of text" "yet more text"))

(setq kill-ring
("some text" "a different pie e of text" "yet more text"))
246 Appendix B: Handling the Kill Ring

the ode should do this:


(setq kill-ring-yank-pointer ( dr kill-ring))
As a result, the kill-ring-yank-pointer will look like this:
kill-ring-yank-pointer
) ("a different pie e of text" "yet more text"))
The a tual setq expression uses the nth dr fun tion to do the job.
As we have seen before (see Se tion 7.3, \nth dr", page 85), the nth dr
fun tion works by repeatedly taking the dr of a list|it takes the dr of
the dr of the dr . . .
The two following expressions produ e the same result:
(setq kill-ring-yank-pointer ( dr kill-ring))

(setq kill-ring-yank-pointer (nth dr 1 kill-ring))


In the rotate-yank-pointer fun tion, however, the rst argument to
nth dr is a rather omplex looking expression with lots of arithmeti inside
of it:
(% (+ arg
(- length
(length kill-ring-yank-pointer)))
length)
As usual, we need to look at the most deeply embedded expression rst
and then work our way towards the light.
The most deeply embedded expression is (length kill-ring-yank-
pointer). This nds the length of the urrent value of the kill-ring-
yank-pointer. (Remember that the kill-ring-yank-pointer is the name
of a variable whose value is a list.)
The measurement of the length is inside the expression:
(- length (length kill-ring-yank-pointer))
In this expression, the rst length is the variable that was assigned the
length of the kill ring in the let statement at the beginning of the fun tion.
(One might think this fun tion would be learer if the variable length were
named length-of-kill-ring instead; but if you look at the text of the
whole fun tion, you will see that it is so short that naming this variable
length is not a bother, unless you are pulling the fun tion apart into very
tiny pie es as we are doing here.)
So the line (- length (length kill-ring-yank-pointer)) tells the dif-
feren e between the length of the kill ring and the length of the list whose
name is kill-ring-yank-pointer.
To see how all this ts into the rotate-yank-pointer fun tion, let's
begin by analyzing the ase where kill-ring-yank-pointer points to the
rst element of the kill ring, just as kill-ring does, and see what happens
when rotate-yank-pointer is alled with an argument of 1.
The % remainder fun tion 247

The variable length and the value of the expression (length kill-ring-
yank-pointer) will be the same sin e the variable length is the length of
the kill ring and the kill-ring-yank-pointer is pointing to the whole kill
ring. Consequently, the value of
(- length (length kill-ring-yank-pointer))
will be zero. Sin e the value of arg will be 1, this will mean that the value
of the whole expression
(+ arg (- length (length kill-ring-yank-pointer)))
will be 1.
Consequently, the argument to nth dr will be found as the result of the
expression
(% 1 length)

The % remainder fun tion


To understand (% 1 length), we need to understand %. A ording to its
do umentation (whi h I just found by typing C-h f % hRETi), the % fun tion
returns the remainder of its rst argument divided by its se ond argument.
For example, the remainder of 5 divided by 2 is 1. (2 goes into 5 twi e with
a remainder of 1.)
What surprises people who don't often do arithmeti is that a smaller
number an be divided by a larger number and have a remainder. In the
example we just used, 5 was divided by 2. We an reverse that and ask,
what is the result of dividing 2 by 5? If you an use fra tions, the answer
is obviously 2/5 or .4; but if, as here, you an only use whole numbers, the
result has to be something di erent. Clearly, 5 an go into 2 zero times, but
what of the remainder? To see what the answer is, onsider a ase that has
to be familiar from hildhood:
 5 divided by 5 is 1 with a remainder of 0;
 6 divided by 5 is 1 with a remainder of 1;
 7 divided by 5 is 1 with a remainder of 2.
 Similarly, 10 divided by 5 is 2 with a remainder of 0;
 11 divided by 5 is 2 with a remainder of 1;
 12 divided by 5 is 1 with a remainder of 2.
By onsidering the ases as parallel, we an see that
 zero divided by 5 must be zero with a remainder of zero;
 1 divided by 5 must be zero with a remainder of 1;
 2 divided by 5 must be zero with a remainder of 2;
and so on.
248 Appendix B: Handling the Kill Ring

So, in this ode, if the value of length is 5, then the result of evaluating
(% 1 5)
is 1. (I just he ked this by pla ing the ursor after the expression and typing
C-x C-e. Indeed, 1 is printed in the e ho area.)

Using % in rotate-yank-pointer
When the kill-ring-yank-pointer points to the beginning of the kill
ring, and the argument passed to rotate-yank-pointer is 1, the % expres-
sion returns 1:
(- length (length kill-ring-yank-pointer))
) 0
therefore,
(+ arg (- length (length kill-ring-yank-pointer)))
) 1
and onsequently:
(% (+ arg (- length (length kill-ring-yank-pointer)))
length)
) 1
regardless of the value of length.
As a result of this, the setq kill-ring-yank-pointer expression simpli es
to:
(setq kill-ring-yank-pointer (nth dr 1 kill-ring))
What it does is now easy to understand. Instead of pointing as it did to the
rst element of the kill ring, the kill-ring-yank-pointer is set to point
to the se ond element.
Clearly, if the argument passed to rotate-yank-pointer is two, then
the kill-ring-yank-pointer is set to (nth dr 2 kill-ring); and so on
for di erent values of the argument.
Similarly, if the kill-ring-yank-pointer starts out pointing to the se -
ond element of the kill ring, its length is shorter than the length of the kill
ring by 1, so the omputation of the remainder is based on the expression
(% (+ arg 1) length). This means that the kill-ring-yank-pointer is
moved from the se ond element of the kill ring to the third element if the
argument passed to rotate-yank-pointer is 1.

Pointing to the last element


The nal question is, what happens if the kill-ring-yank-pointer is
set to the last element of the kill ring? Will a all to rotate-yank-pointer
mean that nothing more an be taken from the kill ring? The answer is no.
What happens is di erent and useful. The kill-ring-yank-pointer is set
to point to the beginning of the kill ring instead.
yank 249

Let's see how this works by looking at the ode, assuming the length of
the kill ring is 5 and the argument passed to rotate-yank-pointer is 1.
When the kill-ring-yank-pointer points to the last element of the kill
ring, its length is 1. The ode looks like this:
(% (+ arg (- length (length kill-ring-yank-pointer))) length)

When the variables are repla ed by their numeri values, the expression
looks like this:
(% (+ 1 (- 5 1)) 5)

This expression an be evaluated by looking at the most embedded inner


expression rst and working outwards: The value of (- 5 1) is 4; the sum
of (+ 1 4) is 5; and the remainder of dividing 5 by 5 is zero. So what
rotate-yank-pointer will do is
(setq kill-ring-yank-pointer (nth dr 0 kill-ring))

whi h will set the kill-ring-yank-pointer to point to the beginning of


the kill ring.
So what happens with su essive alls to rotate-yank-pointer is that
it moves the kill-ring-yank-pointer from element to element in the kill
ring until it rea hes the end; then it jumps ba k to the beginning. And this
is why the kill ring is alled a ring, sin e by jumping ba k to the beginning,
it is as if the list has no end! (And what is a ring, but an entity with no
end?)

B.2 yank
After learning about rotate-yank-pointer, the ode for the yank fun -
tion is almost easy. It has only one tri ky part, whi h is the omputation of
the argument to be passed to rotate-yank-pointer.
The ode looks like this:
(defun yank (&optional arg)
"Reinsert the last stret h of killed text.
More pre isely, reinsert the stret h of killed text most
re ently killed OR yanked.
With just C-U as argument, same but put point in front
(and mark at end). With argument n, reinsert the nth
most re ently killed stret h of killed text.
See also the ommand \\[yank-pop℄."
250 Appendix B: Handling the Kill Ring

(intera tive "*P")


(rotate-yank-pointer (if (listp arg) 0
(if (eq arg '-) -1
(1- arg))))
(push-mark (point))
(insert ( ar kill-ring-yank-pointer))
(if ( onsp arg)
(ex hange-point-and-mark)))
Glan ing over this ode, we an understand the last few lines readily
enough. The mark is pushed, that is, remembered; then the rst element
(the ar) of what the kill-ring-yank-pointer points to is inserted; and
then, if the argument passed the fun tion is a ons, point and mark are
ex hanged so the point is put in the front of the inserted text rather than at
the end. This option is explained in the do umentation. The fun tion itself
is intera tive with "*P". This means it will not work on a read-only bu er,
and that the unpro essed pre x argument is passed to the fun tion.

Passing the argument


The hard part of yank is understanding the omputation that determines
the value of the argument passed to rotate-yank-pointer. Fortunately, it
is not so diÆ ult as it looks at rst sight.
What happens is that the result of evaluating one or both of the if
expressions will be a number and that number will be the argument passed
to rotate-yank-pointer.
Laid out with omments, the ode looks like this:
(if (listp arg) ; if-part
0 ; then-part
(if (eq arg '-) ; else-part, inner if
-1 ; inner if's then-part
(1- arg)))) ; inner if's else-part
This ode onsists of two if expression, one the else-part of the other.
The rst or outer if expression tests whether the argument passed to
yank is a list. Oddly enough, this will be true if yank is alled without an
argument|be ause then it will be passed the value of nil for the optional
argument and an evaluation of (listp nil) returns true! So, if no argument
is passed to yank, the argument passed to rotate-yank-pointer inside of
yank is zero. This means the pointer is not moved and the rst element to
whi h kill-ring-yank-pointer points is inserted, as we expe t. Similarly,
if the argument for yank is C-u, this will be read as a list, so again, a zero will
be passed to rotate-yank-pointer. (C-u produ es an unpro essed pre x
argument of (4), whi h is a list of one element.) At the same time, later in
the fun tion, this argument will be read as a ons so point will be put in the
Passing a negative argument 251

front and mark at the end of the insertion. (The P argument to intera tive
is designed to provide these values for the ase when an optional argument
is not provided or when it is C-u.)
The then-part of the outer if expression handles the ase when there is
no argument or when it is C-u. The else-part handles the other situations.
The else-part is itself another if expression.
The inner if expression tests whether the argument is a minus sign. (This
is done by pressing the hMETAi and - keys at the same time, or the hESCi
key and then the - key). In this ase, the rotate-yank-pointer fun tion
is passed -1 as an argument. This moves the kill-ring-yank-pointer
ba kwards, whi h is what is desired.
If the true-or-false-test of the inner if expression is false (that is, if the
argument is not a minus sign), the else-part of the expression is evaluated.
This is the expression (1- arg). Be ause of the two if expressions, it will
only o ur when the argument is a positive number or when it is a negative
number (not just a minus sign on its own). What (1- arg) does is de rement
the number and return it. (The 1- fun tion subtra ts one from its argument.)
This means that if the argument to rotate-yank-pointer is 1, it is redu ed
to zero, whi h means the rst element to whi h kill-ring-yank-pointer
points is yanked ba k, as you would expe t.

Passing a negative argument


Finally, the question arises, what happens if either the remainder fun -
tion, %, or the nth dr fun tion is passed a negative argument, as they quite
well may?
The answers an be found by a qui k test. When (% -1 5) is evaluated, a
negative number is returned; and if nth dr is alled with a negative number,
it returns the same value as if it were alled with a rst argument of zero.
This an be seen be evaluating the following ode.
Here the `)' points to the result of evaluating the ode pre eding it.
This was done by positioning the ursor after the ode and typing C-x C-e
(eval-last-sexp) in the usual fashion. You an do this if you are reading
this in Info inside of GNU Ema s.
(% -1 5)
) -1
(setq animals '( ats dogs elephants))
) ( ats dogs elephants)
(nth dr 1 animals)
) (dogs elephants)
(nth dr 0 animals)
) ( ats dogs elephants)
252 Appendix B: Handling the Kill Ring

(nth dr -1 animals)
) ( ats dogs elephants)
So, if a minus sign or a negative number is passed to yank, the kill-
ring-yank-point is rotated ba kwards until it rea hes the beginning of the
list. Then it stays there. Unlike the other ase, when it jumps from the end
of the list to the beginning of the list, making a ring, it stops. This makes
sense. You often want to get ba k to the most re ently lipped out pie e of
text, but you don't usually want to insert text from as many as thirty kill
ommands ago. So you need to work through the ring to get to the end, but
won't y le around it inadvertently if you are trying to ome ba k to the
beginning.
In identally, any number passed to yank with a minus sign pre eding
it will be treated as 1. This is evidently a simpli ation for writing the
program. You don't need to jump ba k towards the beginning of the kill
ring more than one pla e at a time and doing this is easier than writing a
fun tion to determine the magnitude of the number that follows the minus
sign.

B.3 yank-pop
After understanding yank, the yank-pop fun tion is easy. Leaving out
the do umentation to save spa e, it looks like this:
(defun yank-pop (arg)
(intera tive "*p")
(if (not (eq last- ommand 'yank))
(error "Previous ommand was not a yank"))
(setq this- ommand 'yank)
(let ((before (< (point) (mark))))
(delete-region (point) (mark))
(rotate-yank-pointer arg)
(set-mark (point))
(insert ( ar kill-ring-yank-pointer))
(if before (ex hange-point-and-mark))))
The fun tion is intera tive with a small `p' so the pre x argument is
pro essed and passed to the fun tion. The ommand an only be used after
a previous yank; otherwise an error message is sent. This he k uses the
variable last- ommand whi h is dis ussed elsewhere. (See Se tion 8.5, \ opy-
region-as-kill", page 102.)
The let lause sets the variable before to true or false depending whether
point is before or after mark and then the region between point and mark
is deleted. This is the region that was just inserted by the previous yank
and it is this text that will be repla ed. Next the kill-ring-yank-pointer
is rotated so that the previously inserted text is not reinserted yet again.
Mark is set at the beginning of the pla e the new text will be inserted and
yank-pop 253

then the rst element to whi h kill-ring-yank-pointer points is inserted.


This leaves point after the new text. If in the previous yank, point was left
before the inserted text, point and mark are now ex hanged so point is again
left in front of the newly inserted text. That is all there is to it!
254 Appendix B: Handling the Kill Ring
A Graph with Labelled Axes 255

Appendix C A Graph with Labelled Axes


Printed axes help you understand a graph. They onvey s ale. In an
earlier hapter (see Chapter 15, \Readying a Graph", page 203), we wrote
the ode to print the body of a graph. Here we write the ode for printing
and labelling verti al and horizontal axes, along with the body itself.
Sin e insertions ll a bu er to the right and below point, the new graph
printing fun tion should rst print the Y or verti al axis, then the body of
the graph, and nally the X or horizontal axis. This sequen e lays out for
us the ontents of the fun tion:
1. Set up ode.
2. Print Y axis.
3. Print body of graph.
4. Print X axis.
Here is an example of how a nished graph should look:
10 -
*
* *
* **
* ***
5 - * *******
* *** *******
*************
***************
1 - ****************
| | | |
1 5 10 15
In this graph, both the verti al and the horizontal axes are labelled with
numbers. However, in some graphs, the horizontal axis is time and would
be better labelled with months, like this:
5 - *
* ** *
*******
********** **
1 - **************
| ^ |
Jan June Jan
Indeed, with a little thought, we an easily ome up with a variety of
verti al and horizontal labelling s hemes. Our task ould be ome ompli-
ated. But ompli ations breed onfusion. Rather than permit this, it is
better hoose a simple labelling s heme for our rst e ort, and to modify or
repla e it later.
256 Appendix C: A Graph with Labelled Axes

These onsiderations suggest the following outline for the print-graph


fun tion:
(defun print-graph (numbers-list)
"do umentation..."
(let ((height ...
...))
(print-Y-axis height ... )
(graph-body-print numbers-list)
(print-X-axis ... )))
We an work on ea h part of the print-graph fun tion de nition in turn.

C.1 The print-graph Varlist


In writing the print-graph fun tion, the rst task is to write the varlist in
the let expression. (We will leave aside for the moment any thoughts about
making the fun tion intera tive or about the ontents of its do umentation
string.)
The varlist should set several values. Clearly, the top of the label for
the verti al axis must be at least the height of the graph, whi h means that
we must obtain this information here. Note that the print-graph-body
fun tion also requires this information. There is no reason to al ulate the
height of the graph in two di erent pla es, so we should hange print-
graph-body from the way we de ned it earlier to take advantage of the
al ulation.
Similarly, both the fun tion for printing the X axis labels and the print-
graph-body fun tion need to learn the value of the width of ea h symbol.
We an perform the al ulation here and hange the de nition for print-
graph-body from the way we de ned it in the previous hapter.
The length of the label for the horizontal axis must be at least as long
as the graph. However, this information is used only in the fun tion that
prints the horizontal axis, so it does not need to be al ulated here.
These thoughts lead us dire tly to the following form for the varlist in
the let for print-graph:
(let ((height (apply 'max numbers-list)) ; First version.
(symbol-width (length graph-blank)))
As we shall see, this expression is not quite right.

C.2 The print-Y-axis Fun tion


The job of the print-Y-axis fun tion is to print a label for the verti al
axis that looks like this:
Side Trip: Compute a Remainder 257

10 -

5 -

1 -
The fun tion should be passed the height of the graph, and then should
onstru t and insert the appropriate numbers and marks.
It is easy enough to see in the gure what the Y axis label should look
like; but to say in words, and then to write a fun tion de nition to do the
job is another matter. It is not quite true to say that we want a number
and a ti every ve lines: there are only three lines between the `1' and the
`5' (lines 2, 3, and 4), but four lines between the `5' and the `10' (lines 6, 7,
8, and 9). It is better to say that we want a number and a ti mark on the
base line (number 1) and then that we want a number and a ti on the fth
line from the bottom and on every line that is a multiple of ve.
The next issue is what height the label should be? Suppose the maximum
height of tallest olumn of the graph is seven. Should the highest label on
the Y axis be `5 -', and should the graph sti k up above the label? Or should
the highest label be `7 -', and mark the peak of the graph? Or should the
highest label be 10 -, whi h is a multiple of ve, and be higher than the
topmost value of the graph?
The latter form is preferred. Most graphs are drawn within re tangles
whose sides are an integral number of steps long|5, 10, 15, and so on for a
step distan e of ve. But as soon as we de ide to use a step height for the ver-
ti al axis, we dis over that the simple expression in the varlist for omputing
the height is wrong. The expression is (apply 'max numbers-list). This
returns the pre ise height, not the maximum height plus whatever is ne es-
sary to round up to the nearest multiple of ve. A more omplex expression
is required.
As usual in ases like this, a omplex problem be omes simpler if it is
divided into several smaller problems.
First, onsider the ase when the highest value of the graph is an integral
multiple of ve|when it is 5, 10, 15 ,or some higher multiple of ve. We
an use this value as the Y axis height.
A fairly simply way to determine whether a number is a multiple of ve
is to divide it by ve and see if the division results in a remainder. If there is
no remainder, the number is a multiple of ve. Thus, seven divided by ve
has a remainder of two, and seven is not an integral multiple of ve. Put in
slightly di erent language, more reminis ent of the lassroom, ve goes into
258 Appendix C: A Graph with Labelled Axes

seven on e, with a remainder of two. However, ve goes into ten twi e, with
no remainder: ten is an integral multiple of ve.

C.2.1 Side Trip: Compute a Remainder


In Lisp, the fun tion for omputing a remainder is %. The fun tion returns
the remainder of its rst argument divided by its se ond argument. As
it happens, % is a fun tion in Ema s Lisp that you annot dis over using
apropos: you nd nothing if you type M-x apropos hRETi remainder hRETi.
The only way to learn of the existen e of % is to read about it in a book
su h as this or in the Ema s Lisp sour es. The % fun tion is used in the
ode for rotate-yank-pointer, whi h is des ribed in an appendix. (See
Se tion B.1.1, \The Body of rotate-yank-pointer", page 244.)
You an try the % fun tion by evaluating the following two expressions:
(% 7 5)

(% 10 5)
The rst expression returns 2 and the se ond expression returns 0.
To test whether the returned value is zero or some other number, we an
use the zerop fun tion. This fun tion returns t if its argument, whi h must
be a number, is zero.
(zerop (% 7 5))
) nil

(zerop (% 10 5))
) t
Thus, the following expression will return t if the height of the graph is
evenly divisible by ve:
(zerop (% height 5))
(The value of height, of ourse, an be found from (apply 'max numbers-
list).)
On the other hand, if the value of height is not a multiple of ve, we want
to reset the value to the next higher multiple of ve. This is straightforward
arithmeti using fun tions with whi h we are already familiar. First, we
divide the value of height by ve to determine how many times ve goes
into the number. Thus, ve goes into twelve twi e. If we add one to this
quotient and multiply by ve, we will obtain the value of the next multiple
of ve that is larger than the height. Five goes into twelve twi e. Add one
to two, and multiply by ve; the result is fteen, whi h is the next multiple
of ve that is higher than twelve. The Lisp expression for this is:
(* (1+ (/ height 5)) 5)
For example, if you evaluate the following, the result is 15:
(* (1+ (/ 12 5)) 5)
Constru t a Y Axis Element 259

All through this dis ussion, we have been using ` ve' as the value for
spa ing labels on the Y axis; but we may want to use some other value. For
generality, we should repla e ` ve' with a variable to whi h we an assign
a value. The best name I an think of for this variable is Y-axis-label-
spa ing.
Using this term, and an if expression, we produ e the following:
(if (zerop (% height Y-axis-label-spa ing))
height
;; else
(* (1+ (/ height Y-axis-label-spa ing))
Y-axis-label-spa ing))
This expression returns the value of height itself if the height is an even
multiple of the value of the Y-axis-label-spa ing or else it omputes and
returns a value of height that is equal to the next higher multiple of the
value of the Y-axis-label-spa ing.
We an now in lude this expression in the let expression of the print-
graph fun tion (after rst setting the value of Y-axis-label-spa ing):
(defvar Y-axis-label-spa ing 5
"Number of lines from one Y axis label to next.")
...
(let* ((height (apply 'max numbers-list))
(height-of-top-line
(if (zerop (% height Y-axis-label-spa ing))
height
;; else
(* (1+ (/ height Y-axis-label-spa ing))
Y-axis-label-spa ing)))
(symbol-width (length graph-blank))))
...
(Note use of the let* fun tion: the initial value of height is omputed on e
by the (apply 'max numbers-list) expression and then the resulting value
of height is used to ompute its nal value. See \The let* expression",
page 156, for more about let*.)

C.2.2 Constru t a Y Axis Element


When we print the verti al axis, we want to insert strings su h as `5 -'
and `10 - ' every ve lines. Moreover, we want the numbers and dashes to
line up, so shorter numbers must be padded with leading spa es. If some
of the strings use two digit numbers, the strings with single digit numbers
must in lude a leading blank spa e before the number.
To gure out the length of the number, the length fun tion is used. But
the length fun tion works only with a string, not with a number. So the
260 Appendix C: A Graph with Labelled Axes

number has to be onverted from being a number to being a string. This is


done with the number-to-string fun tion. For example,
(length (number-to-string 35))
) 2

(length (number-to-string 100))


) 3
(number-to-string is also alled int-to-string; you will see this alterna-
tive name in various sour es.)
In addition, in ea h label, ea h number is followed by a string su h as
` - ', whi h we will all the Y-axis-ti marker. This variable is de ned
with defvar:
(defvar Y-axis-ti " - "
"String that follows number in a Y axis label.")
The length of the Y label is the sum of the length of the Y axis ti mark
and the length of the number of the top of the graph.
(length ( on at (number-to-string height) Y-axis-ti )))
This value will be al ulated by the print-graph fun tion in its varlist as
full-Y-label-width and passed on. (Note that we did not think to in lude
this in the varlist when we rst proposed it.)
To make a omplete verti al axis label, a ti mark is on atenated with
a number; and the two together may be pre eded by one or more spa es
depending on how long the number is. The label onsists of three parts:
the (optional) leading spa es, the number, and the ti mark. The fun tion
is passed the value of the number for the spe i row, and the value of the
width of the top line, whi h is al ulated (just on e) by print-graph.
(defun Y-axis-element (number full-Y-label-width)
"Constru t a NUMBERed label element.
A numbered element looks like this ` 5 - ',
and is padded as needed so all line up with
the element for the largest number."
(let* ((leading-spa es
(- full-Y-label-width
(length
( on at (number-to-string number)
Y-axis-ti )))))
( on at
(make-string leading-spa es ? )
(number-to-string number)
Y-axis-ti )))
The Y-axis-element fun tion on atenates together the leading spa es,
if any; the number, as a string; and the ti mark.
The Not Quite Final Version of print-Y-axis 261

To gure out how many leading spa es the label will need, the fun tion
subtra ts the a tual length of the label|the length of the number plus the
length of the ti mark|from the desired label width.
Blank spa es are inserted using the make-string fun tion. This fun tion
takes two arguments: the rst tells it how long the string will be and the
se ond is a symbol for the hara ter to insert, in a spe ial format. The
format is a question mark followed by a blank spa e, like this, `? '. See
se tion \Chara ter Type" in The GNU Ema s Lisp Referen e Manual, for a
des ription of the syntax for hara ters.
The number-to-string fun tion is used in the on atenation expression,
to onvert the number to a string that is on atenated with the leading
spa es and the ti mark.

C.2.3 Create a Y Axis Column


The pre eding fun tions provide all the tools needed to onstru t a fun -
tion that generates a list of numbered and blank strings to insert as the label
for the verti al axis:
(defun Y-axis- olumn (height width-of-label)
"Constru t list of Y axis labels and blank strings.
For HEIGHT of line above base and WIDTH-OF-LABEL."
(let (Y-axis)
(while (> height 1)
(if (zerop (% height Y-axis-label-spa ing))
;; Insert label.
(setq Y-axis
( ons
(Y-axis-element height width-of-label)
Y-axis))
;; Else, insert blanks.
(setq Y-axis
( ons
(make-string width-of-label ? )
Y-axis)))
(setq height (1- height)))
;; Insert base line.
(setq Y-axis
( ons (Y-axis-element 1 width-of-label) Y-axis))
(nreverse Y-axis)))
In this fun tion, we start with the value of height and repetitively sub-
tra t one from its value. After ea h subtra tion, we test to see whether
the value is an integral multiple of the Y-axis-label-spa ing. If it is,
we onstru t a numbered label using the Y-axis-element fun tion; if not,
262 Appendix C: A Graph with Labelled Axes

we onstru t a blank label using the make-string fun tion. The base line
onsists of the number one followed by a ti mark.

C.2.4 The Not Quite Final Version of print-Y-axis


The list onstru ted by the Y-axis- olumn fun tion is passed to the
print-Y-axis fun tion, whi h inserts the list as a olumn.
(defun print-Y-axis (height full-Y-label-width)
"Insert Y axis using HEIGHT and FULL-Y-LABEL-WIDTH.
Height must be the maximum height of the graph.
Full width is the width of the highest label element."
;; Value of height and full-Y-label-width
;; are passed by `print-graph'.
(let ((start (point)))
(insert-re tangle
(Y-axis- olumn height full-Y-label-width))
;; Pla e point ready for inserting graph.
(goto- har start)
;; Move point forward by value of full-Y-label-width
(forward- har full-Y-label-width)))
The print-Y-axis uses the insert-re tangle fun tion to insert the Y
axis labels reated by the Y-axis- olumn fun tion. In addition, it pla es
point at the orre t position for printing the body of the graph.
You an test print-Y-axis:
1. Install
Y-axis-label-spa ing
Y-axis-ti
Y-axis-element
Y-axis- olumn
print-Y-axis
2. Copy the following expression:
(print-Y-axis 12 5)
3. Swit h to the `*s rat h*' bu er and pla e the ursor where you want
the axis labels to start.
4. Type M-: (eval-expression).
5. Yank the graph-body-print expression into the minibu er with C-y
(yank).
6. Press hRETi to evaluate the expression.
Ema s will print labels verti ally, the top one being `10 - '. (The print-
graph fun tion will pass the value of height-of-top-line, whi h in this
ase would end up as 15.)
X Axis Ti Marks 263

C.3 The print-X-axis Fun tion


X axis labels are mu h like Y axis labels, ex ept that the ti s are on a
line above the numbers. Labels should look like this:
| | | |
1 5 10 15
The rst ti is under the rst olumn of the graph and is pre eded by
several blank spa es. These spa es provide room in rows above for the Y
axis labels. The se ond, third, fourth, and subsequent ti s are all spa ed
equally, a ording to the value of X-axis-label-spa ing.
The se ond row of the X axis onsists of numbers, pre eded by several
blank spa es and also separated a ording to the value of the variable X-
axis-label-spa ing.
The value of the variable X-axis-label-spa ing should itself be mea-
sured in units of symbol-width, sin e you may want to hange the width
of the symbols that you are using to print the body of the graph without
hanging the ways the graph is labelled.
The print-X-axis fun tion is onstru ted in more or less the same fash-
ion as the print-Y-axis fun tion ex ept that it has two lines: the line of
ti marks and the numbers. We will write a separate fun tion to print ea h
line and then ombine them within the print-X-axis fun tion.
This is a three step pro ess:
1. Write a fun tion to print the X axis ti marks, print-X-axis-ti -line.
2. Write a fun tion to print the X numbers, print-X-axis-numbered-
line.
3. Write a fun tion to print both lines, the print-X-axis fun tion, using
print-X-axis-ti -line and print-X-axis-numbered-line.

C.3.1 X Axis Ti Marks


The rst fun tion should print the X axis ti marks. We must spe ify the
ti marks themselves and their spa ing:
(defvar X-axis-label-spa ing
(if (boundp 'graph-blank)
(* 5 (length graph-blank)) 5)
"Number of units from one X axis label to next.")
(Note that the value of graph-blank is set by another defvar. The
boundp predi ate he ks whether it has already been set; boundp returns
nil if it has not. If graph-blank were unbound and we did not use
this onditional onstru tion, in GNU Ema s 21, we would enter the de-
bugger and see an error message saying `Debugger entered--Lisp error:
(void-variable graph-blank)'.)
264 Appendix C: A Graph with Labelled Axes

Here is the defvar for X-axis-ti -symbol:


(defvar X-axis-ti -symbol "|"
"String to insert to point to a olumn in X axis.")

The goal is to make a line that looks like this:


| | | |
The rst ti is indented so that it is under the rst olumn, whi h is
indented to provide spa e for the Y axis labels.
A ti element onsists of the blank spa es that stret h from one ti to the
next plus a ti symbol. The number of blanks is determined by the width of
the ti symbol and the X-axis-label-spa ing.
The ode looks like this:
;;; X-axis-ti -element
...
( on at
(make-string
;; Make a string of blanks.
(- (* symbol-width X-axis-label-spa ing)
(length X-axis-ti -symbol))
? )
;; Con atenate blanks with ti symbol.
X-axis-ti -symbol)
...
Next, we determine how many blanks are needed to indent the rst ti
mark to the rst olumn of the graph. This uses the value of full-Y-label-
width passed it by the print-graph fun tion.
The ode to make X-axis-leading-spa es looks like this:
;; X-axis-leading-spa es
...
(make-string full-Y-label-width ? )
...
We also need to determine the length of the horizontal axis, whi h is the
length of the numbers list, and the number of ti s in the horizontal axis:
;; X-length
...
(length numbers-list)
;; ti -width
...
(* symbol-width X-axis-label-spa ing)
X Axis Ti Marks 265

;; number-of-X-ti s
(if (zerop (% (X-length ti -width)))
(/ (X-length ti -width))
(1+ (/ (X-length ti -width))))

All this leads us dire tly to the fun tion for printing the X axis ti line:
(defun print-X-axis-ti -line
(number-of-X-ti s X-axis-leading-spa es X-axis-ti -element)
"Print ti s for X axis."
(insert X-axis-leading-spa es)
(insert X-axis-ti -symbol) ; Under rst olumn.
;; Insert se ond ti in the right spot.
(insert ( on at
(make-string
(- (* symbol-width X-axis-label-spa ing)
;; Insert white spa e up to se ond ti symbol.
(* 2 (length X-axis-ti -symbol)))
? )
X-axis-ti -symbol))
;; Insert remaining ti s.
(while (> number-of-X-ti s 1)
(insert X-axis-ti -element)
(setq number-of-X-ti s (1- number-of-X-ti s))))

The line of numbers is equally straightforward:


First, we reate a numbered element with blank spa es before ea h num-
ber:
(defun X-axis-element (number)
"Constru t a numbered X axis element."
(let ((leading-spa es
(- (* symbol-width X-axis-label-spa ing)
(length (number-to-string number)))))
( on at (make-string leading-spa es ? )
(number-to-string number))))

Next, we reate the fun tion to print the numbered line, starting with
the number \1" under the rst olumn:
(defun print-X-axis-numbered-line
(number-of-X-ti s X-axis-leading-spa es)
"Print line of X-axis numbers"
(let ((number X-axis-label-spa ing))
(insert X-axis-leading-spa es)
(insert "1")
266 Appendix C: A Graph with Labelled Axes

(insert ( on at
(make-string
;; Insert white spa e up to next number.
(- (* symbol-width X-axis-label-spa ing) 2)
? )
(number-to-string number)))
;; Insert remaining numbers.
(setq number (+ number X-axis-label-spa ing))
(while (> number-of-X-ti s 1)
(insert (X-axis-element number))
(setq number (+ number X-axis-label-spa ing))
(setq number-of-X-ti s (1- number-of-X-ti s)))))
Finally, we need to write the print-X-axis that uses print-X-axis-
ti -line and print-X-axis-numbered-line.
The fun tion must determine the lo al values of the variables used by both
print-X-axis-ti -line and print-X-axis-numbered-line, and then it
must all them. Also, it must print the arriage return that separates the
two lines.
The fun tion onsists of a varlist that spe i es ve lo al variables, and
alls to ea h of the two line printing fun tions:
(defun print-X-axis (numbers-list)
"Print X axis labels to length of NUMBERS-LIST."
(let* ((leading-spa es
(make-string full-Y-label-width ? ))
;; symbol-width is provided by graph-body-print
(ti -width (* symbol-width X-axis-label-spa ing))
(X-length (length numbers-list))
(X-ti
( on at
(make-string
;; Make a string of blanks.
(- (* symbol-width X-axis-label-spa ing)
(length X-axis-ti -symbol))
? )
;; Con atenate blanks with ti symbol.
X-axis-ti -symbol))
(ti -number
(if (zerop (% X-length ti -width))
(/ X-length ti -width)
(1+ (/ X-length ti -width)))))
(print-X-axis-ti -line ti -number leading-spa es X-ti )
(insert "\n")
(print-X-axis-numbered-line ti -number leading-spa es)))
Printing the Whole Graph 267

You an test print-X-axis:


1. Install X-axis-ti -symbol, X-axis-label-spa ing, print-X-axis-
ti -line, as well as X-axis-element, print-X-axis-numbered-line,
and print-X-axis.
2. Copy the following expression:
(progn
(let ((full-Y-label-width 5)
(symbol-width 1))
(print-X-axis
'(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))))
3. Swit h to the `*s rat h*' bu er and pla e the ursor where you want
the axis labels to start.
4. Type M-: (eval-expression).
5. Yank the test expression into the minibu er with C-y (yank).
6. Press hRETi to evaluate the expression.
Ema s will print the horizontal axis like this:
| | | | |
1 5 10 15 20

C.4 Printing the Whole Graph


Now we are nearly ready to print the whole graph.
The fun tion to print the graph with the proper labels follows the out-
line we reated earlier (see Appendix C, \A Graph with Labelled Axes",
page 255), but with additions.
Here is the outline:
(defun print-graph (numbers-list)
"do umentation..."
(let ((height ...
...))
(print-Y-axis height ... )
(graph-body-print numbers-list)
(print-X-axis ... )))
The nal version is di erent from what we planned in two ways: rst, it
ontains additional values al ulated on e in the varlist; se ond, it arries
an option to spe ify the labels' in rement per row. This latter feature turns
out to be essential; otherwise, a graph may have more rows than t on a
display or on a sheet of paper.
268 Appendix C: A Graph with Labelled Axes

This new feature requires a hange to the Y-axis- olumn fun tion, to
add verti al-step to it. The fun tion looks like this:

;;; Final version.


(defun Y-axis- olumn
(height width-of-label &optional verti al-step)
"Constru t list of labels for Y axis.
HEIGHT is maximum height of graph.
WIDTH-OF-LABEL is maximum width of label.
VERTICAL-STEP, an option, is a positive integer
that spe ifies how mu h a Y axis label in rements
for ea h line. For example, a step of 5 means
that ea h line is five units of the graph."
(let (Y-axis
(number-per-line (or verti al-step 1)))
(while (> height 1)
(if (zerop (% height Y-axis-label-spa ing))
;; Insert label.
(setq Y-axis
( ons
(Y-axis-element
(* height number-per-line)
width-of-label)
Y-axis))
;; Else, insert blanks.
(setq Y-axis
( ons
(make-string width-of-label ? )
Y-axis)))
(setq height (1- height)))
;; Insert base line.
(setq Y-axis ( ons (Y-axis-element
(or verti al-step 1)
width-of-label)
Y-axis))
(nreverse Y-axis)))

The values for the maximum height of graph and the width of a symbol
are omputed by print-graph in its let expression; so graph-body-print
must be hanged to a ept them.
Printing the Whole Graph 269

;;; Final version.


(defun graph-body-print (numbers-list height symbol-width)
"Print a bar graph of the NUMBERS-LIST.
The numbers-list onsists of the Y-axis values.
HEIGHT is maximum height of graph.
SYMBOL-WIDTH is number of ea h olumn."
(let (from-position)
(while numbers-list
(setq from-position (point))
(insert-re tangle
( olumn-of-graph height ( ar numbers-list)))
(goto- har from-position)
(forward- har symbol-width)
;; Draw graph olumn by olumn.
(sit-for 0)
(setq numbers-list ( dr numbers-list)))
;; Pla e point for X axis labels.
(forward-line height)
(insert "\n")))

Finally, the ode for the print-graph fun tion:


;;; Final version.
(defun print-graph
(numbers-list &optional verti al-step)
"Print labelled bar graph of the NUMBERS-LIST.
The numbers-list onsists of the Y-axis values.
Optionally, VERTICAL-STEP, a positive integer,
spe ifies how mu h a Y axis label in rements for
ea h line. For example, a step of 5 means that
ea h row is five units."
(let* ((symbol-width (length graph-blank))
;; height is both the largest number
;; and the number with the most digits.
(height (apply 'max numbers-list))
(height-of-top-line
(if (zerop (% height Y-axis-label-spa ing))
height
;; else
(* (1+ (/ height Y-axis-label-spa ing))
Y-axis-label-spa ing)))
(verti al-step (or verti al-step 1))
(full-Y-label-width
(length
270 Appendix C: A Graph with Labelled Axes

( on at
(number-to-string
(* height-of-top-line verti al-step))
Y-axis-ti ))))
(print-Y-axis
height-of-top-line full-Y-label-width verti al-step)
(graph-body-print
numbers-list height-of-top-line symbol-width)
(print-X-axis numbers-list)))

C.4.1 Testing print-graph


We an test the print-graph fun tion with a short list of numbers:
1. Install the nal versions of Y-axis- olumn, graph-body-print, and
print-graph (in addition to the rest of the ode.)
2. Copy the following expression:
(print-graph '(3 2 5 6 7 5 3 4 6 4 3 2 1))
3. Swit h to the `*s rat h*' bu er and pla e the ursor where you want
the axis labels to start.
4. Type M-: (eval-expression).
5. Yank the test expression into the minibu er with C-y (yank).
6. Press hRETi to evaluate the expression.
Ema s will print a graph that looks like this:
10 -

*
** *
5 - **** *
**** ***
* *********
************
1 - *************

| | | |
1 5 10 15
On the other hand, if you pass print-graph a verti al-step value of
2, by evaluating this expression:
(print-graph '(3 2 5 6 7 5 3 4 6 4 3 2 1) 2)
Graphing Numbers of Words and Symbols 271

The graph looks like this:


20 -

*
** *
10 - **** *
**** ***
* *********
************
2 - *************

| | | |
1 5 10 15

(A question: is the `2' on the bottom of the verti al axis a bug or a feature?
If you think it is a bug, and should be a `1' instead, (or even a `0'), you an
modify the sour es.)

C.4.2 Graphing Numbers of Words and Symbols


Now for the graph for whi h all this ode was written: a graph that shows
how many fun tion de nitions ontain fewer than 10 words and symbols, how
many ontain between 10 and 19 words and symbols, how many ontain
between 20 and 29 words and symbols, and so on.
This is a multi-step pro ess. First make sure you have loaded all the
requisite ode.
It is a good idea to reset the value of top-of-ranges in ase you have
set it to some di erent value. You an evaluate the following:
(setq top-of-ranges
'(10 20 30 40 50
60 70 80 90 100
110 120 130 140 150
160 170 180 190 200
210 220 230 240 250
260 270 280 290 300)

Next reate a list of the number of words and symbols in ea h range.


272 Appendix C: A Graph with Labelled Axes

Evaluate the following:


(setq list-for-graph
(defuns-per-range
(sort
(re ursive-lengths-list-many-files
(dire tory-files "/usr/lo al/ema s/lisp"
t ".+el$"))
'<)
top-of-ranges))

On my ma hine, this takes about an hour. It looks though 303 Lisp les in
my opy of Ema s version 19.23. After all that omputing, the list-for-
graph has this value:
(537 1027 955 785 594 483 349 292 224 199 166 120 116 99
90 80 67 48 52 45 41 33 28 26 25 20 12 28 11 13 220)

This means that my opy of Ema s has 537 fun tion de nitions with fewer
than 10 words or symbols in them, 1,027 fun tion de nitions with 10 to 19
words or symbols in them, 955 fun tion de nitions with 20 to 29 words or
symbols in them, and so on.
Clearly, just by looking at this list we an see that most fun tion de ni-
tions ontain ten to thirty words and symbols.
Now for printing. We do not want to print a graph that is 1,030 lines
high . . . Instead, we should print a graph that is fewer than twenty- ve
lines high. A graph that height an be displayed on almost any monitor,
and easily printed on a sheet of paper.
This means that ea h value in list-for-graph must be redu ed to one-
ftieth its present value.
Here is a short fun tion to do just that, using two fun tions we have not
yet seen, map ar and lambda.
(defun one-fiftieth (full-range)
"Return list, ea h number one-fiftieth of previous."
(map ar '(lambda (arg) (/ arg 50)) full-range))

C.4.3 A lambda Expression: Useful Anonymity


lambda is the symbol for an anonymous fun tion, a fun tion without a
name. Every time you use an anonymous fun tion, you need to in lude its
whole body.
The map ar Fun tion 273

Thus,
(lambda (arg) (/ arg 50))
is a fun tion de nition that says `return the value resulting from dividing
whatever is passed to me as arg by 50'.
Earlier, for example, we had a fun tion multiply-by-seven; it multiplied
its argument by 7. This fun tion is similar, ex ept it divides its argument by
50; and, it has no name. The anonymous equivalent of multiply-by-seven
is:
(lambda (number) (* 7 number))
(See Se tion 3.1, \The defun Spe ial Form", page 29.)
If we want to multiply 3 by 7, we an write:

(multiply-by-seven 3)

function argument

This expression returns 21.


Similarly, we an write:

((lambda (number) (* 7 number)) 3)

anonymous function argument

If we want to divide 100 by 50, we an write:

((lambda (arg) (/ arg 50)) 100)

anonymous function argument

This expression returns 2. The 100 is passed to the fun tion, whi h divides
that number by 50.
See se tion \Lambda Expressions" in The GNU Ema s Lisp Referen e
Manual, for more about lambda. Lisp and lambda expressions derive from
the Lambda Cal ulus.
274 Appendix C: A Graph with Labelled Axes

C.4.4 The map ar Fun tion


map ar is a fun tion that alls its rst argument with ea h element of its
se ond argument, in turn. The se ond argument must be a sequen e.
The `map' part of the name omes from the mathemati al phrase, `map-
ping over a domain', meaning to apply a fun tion to ea h of the elements in
a domain. The mathemati al phrase is based on the metaphor of a surveyor
walking, one step at a time, over an area he is mapping. And ` ar', of ourse,
omes from the Lisp notion of the rst of a list.
For example,
(map ar '1+ '(2 4 6))
) (3 5 7)
The fun tion 1+ whi h adds one to its argument, is exe uted on ea h element
of the list, and a new list is returned.
Contrast this with apply, whi h applies its rst argument to all the re-
maining. (See Chapter 15, \Readying a Graph", page 203, for a explanation
of apply.)
In the de nition of one-fiftieth, the rst argument is the anonymous
fun tion:
(lambda (arg) (/ arg 50))
and the se ond argument is full-range, whi h will be bound to list-for-
graph.
The whole expression looks like this:
(map ar '(lambda (arg) (/ arg 50)) full-range))
See se tion \Mapping Fun tions" in The GNU Ema s Lisp Referen e
Manual, for more about map ar.
Using the one-fiftieth fun tion, we an generate a list in whi h ea h
element is one- ftieth the size of the orresponding element in list-for-
graph.
(setq fiftieth-list-for-graph
(one-fiftieth list-for-graph))
The resulting list looks like this:
(10 20 19 15 11 9 6 5 4 3 3 2 2
1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 4)
This, we are almost ready to print! (We also noti e the loss of information:
many of the higher ranges are 0, meaning that fewer than 50 defuns had
that many words or symbols|but not ne essarily meaning that none had
that many words or symbols.)

C.4.5 Another Bug . . . Most Insidious


I said `almost ready to print'! Of ourse, there is a bug in the print-
graph fun tion . . . It has a verti al-step option, but not a horizontal-
Another Bug . . . Most Insidious 275

step option. The top-of-range s ale goes from 10 to 300 by tens. But the
print-graph fun tion will print only by ones.
This is a lassi example of what some onsider the most insidious type
of bug, the bug of omission. This is not the kind of bug you an nd by
studying the ode, for it is not in the ode; it is an omitted feature. Your
best a tions are to try your program early and often; and try to arrange,
as mu h as you an, to write ode that is easy to understand and easy to
hange. Try to be aware, whenever you an, that whatever you have written,
will be rewritten, if not soon, eventually. A hard maxim to follow.
It is the print-X-axis-numbered-line fun tion that needs the work;
and then the print-X-axis and the print-graph fun tions need to be
adapted. Not mu h needs to be done; there is one ni ety: the numbers
ought to line up under the ti marks. This takes a little thought.
Here is the orre ted print-X-axis-numbered-line:
(defun print-X-axis-numbered-line
(number-of-X-ti s X-axis-leading-spa es
&optional horizontal-step)
"Print line of X-axis numbers"
(let ((number X-axis-label-spa ing)
(horizontal-step (or horizontal-step 1)))
(insert X-axis-leading-spa es)
;; Delete extra leading spa es.
(delete- har
(- (1-
(length (number-to-string horizontal-step)))))
(insert ( on at
(make-string
;; Insert white spa e.
(- (* symbol-width
X-axis-label-spa ing)
(1-
(length
(number-to-string horizontal-step)))
2)
? )
(number-to-string
(* number horizontal-step))))
;; Insert remaining numbers.
(setq number (+ number X-axis-label-spa ing))
(while (> number-of-X-ti s 1)
(insert (X-axis-element
(* number horizontal-step)))
(setq number (+ number X-axis-label-spa ing))
(setq number-of-X-ti s (1- number-of-X-ti s)))))
276 Appendix C: A Graph with Labelled Axes

If you are reading this in Info, you an see the new versions of print-X-
axis print-graph and evaluate them. If you are reading this in a printed
book, you an see the hanged lines here (the full text is too mu h to print).
(defun print-X-axis (numbers-list horizontal-step)
...
(print-X-axis-numbered-line
ti -number leading-spa es horizontal-step))
(defun print-graph
(numbers-list
&optional verti al-step horizontal-step)
...
(print-X-axis numbers-list horizontal-step))
The Printed Graph 277

C.4.6 The Printed Graph


When made and installed, you an all the print-graph ommand like
this:
(print-graph fiftieth-list-for-graph 50 10)
Here is the graph:

1000 - *
**
**
**
**
750 - ***
***
***
***
****
500 - *****
******
******
******
*******
250 - ********
********* *
*********** *
************* *
50 - ***************** * *
| | | | | | | |
10 50 100 150 200 250 300 350

The largest group of fun tions ontain 10 { 19 words and symbols ea h.


278 Appendix C: A Graph with Labelled Axes
GNU Free Do umentation Li ense 279

Appendix D GNU Free Do umentation


Li ense
Version 1.1, Mar h 2000
Copyright
2000 Free Software Foundation, In .
59 Temple Pla e, Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to opy and distribute verbatim opies
of this li ense do ument, but hanging it is not allowed.
0. PREAMBLE
The purpose of this Li ense is to make a manual, textbook, or other
written do ument free in the sense of freedom: to assure everyone the
e e tive freedom to opy and redistribute it, with or without modifying
it, either ommer ially or non ommer ially. Se ondarily, this Li ense
preserves for the author and publisher a way to get redit for their
work, while not being onsidered responsible for modi ations made by
others.
This Li ense is a kind of \ opyleft", whi h means that derivative works
of the do ument must themselves be free in the same sense. It om-
plements the GNU General Publi Li ense, whi h is a opyleft li ense
designed for free software.
We have designed this Li ense in order to use it for manuals for free soft-
ware, be ause free software needs free do umentation: a free program
should ome with manuals providing the same freedoms that the soft-
ware does. But this Li ense is not limited to software manuals; it an
be used for any textual work, regardless of subje t matter or whether it
is published as a printed book. We re ommend this Li ense prin ipally
for works whose purpose is instru tion or referen e.
1. APPLICABILITY AND DEFINITIONS
This Li ense applies to any manual or other work that ontains a noti e
pla ed by the opyright holder saying it an be distributed under the
terms of this Li ense. The \Do ument", below, refers to any su h man-
ual or work. Any member of the publi is a li ensee, and is addressed
as \you".
A \Modi ed Version" of the Do ument means any work ontaining the
Do ument or a portion of it, either opied verbatim, or with modi a-
tions and/or translated into another language.
A \Se ondary Se tion" is a named appendix or a front-matter se tion
of the Do ument that deals ex lusively with the relationship of the pub-
lishers or authors of the Do ument to the Do ument's overall subje t
(or to related matters) and ontains nothing that ould fall dire tly
within that overall subje t. (For example, if the Do ument is in part
a textbook of mathemati s, a Se ondary Se tion may not explain any
280 Appendix D: GNU Free Do umentation Li ense

mathemati s.) The relationship ould be a matter of histori al onne -


tion with the subje t or with related matters, or of legal, ommer ial,
philosophi al, ethi al or politi al position regarding them.
The \Invariant Se tions" are ertain Se ondary Se tions whose titles are
designated, as being those of Invariant Se tions, in the noti e that says
that the Do ument is released under this Li ense.
The \Cover Texts" are ertain short passages of text that are listed, as
Front-Cover Texts or Ba k-Cover Texts, in the noti e that says that the
Do ument is released under this Li ense.
A \Transparent" opy of the Do ument means a ma hine-readable opy,
represented in a format whose spe i ation is available to the general
publi , whose ontents an be viewed and edited dire tly and straight-
forwardly with generi text editors or (for images omposed of pixels)
generi paint programs or (for drawings) some widely available drawing
editor, and that is suitable for input to text formatters or for automati
translation to a variety of formats suitable for input to text formatters.
A opy made in an otherwise Transparent le format whose markup
has been designed to thwart or dis ourage subsequent modi ation by
readers is not Transparent. A opy that is not \Transparent" is alled
\Opaque".
Examples of suitable formats for Transparent opies in lude plain as ii
without markup, Texinfo input format, LaTEX input format, sgml
or xml using a publi ly available dtd, and standard- onforming sim-
ple html designed for human modi ation. Opaque formats in lude
PostS ript, pdf, proprietary formats that an be read and edited only
by proprietary word pro essors, sgml or xml for whi h the dtd and/or
pro essing tools are not generally available, and the ma hine-generated
html produ ed by some word pro essors for output purposes only.
The \Title Page" means, for a printed book, the title page itself, plus
su h following pages as are needed to hold, legibly, the material this
Li ense requires to appear in the title page. For works in formats whi h
do not have any title page as su h, \Title Page" means the text near the
most prominent appearan e of the work's title, pre eding the beginning
of the body of the text.
2. VERBATIM COPYING
You may opy and distribute the Do ument in any medium, either om-
mer ially or non ommer ially, provided that this Li ense, the opyright
noti es, and the li ense noti e saying this Li ense applies to the Do u-
ment are reprodu ed in all opies, and that you add no other onditions
whatsoever to those of this Li ense. You may not use te hni al mea-
sures to obstru t or ontrol the reading or further opying of the opies
you make or distribute. However, you may a ept ompensation in ex-
hange for opies. If you distribute a large enough number of opies you
must also follow the onditions in se tion 3.
GNU Free Do umentation Li ense 281

You may also lend opies, under the same onditions stated above, and
you may publi ly display opies.
3. COPYING IN QUANTITY
If you publish printed opies of the Do ument numbering more than
100, and the Do ument's li ense noti e requires Cover Texts, you must
en lose the opies in overs that arry, learly and legibly, all these Cover
Texts: Front-Cover Texts on the front over, and Ba k-Cover Texts on
the ba k over. Both overs must also learly and legibly identify you as
the publisher of these opies. The front over must present the full title
with all words of the title equally prominent and visible. You may add
other material on the overs in addition. Copying with hanges limited
to the overs, as long as they preserve the title of the Do ument and
satisfy these onditions, an be treated as verbatim opying in other
respe ts.
If the required texts for either over are too voluminous to t legibly,
you should put the rst ones listed (as many as t reasonably) on the
a tual over, and ontinue the rest onto adja ent pages.
If you publish or distribute Opaque opies of the Do ument numbering
more than 100, you must either in lude a ma hine-readable Transpar-
ent opy along with ea h Opaque opy, or state in or with ea h Opaque
opy a publi ly-a essible omputer-network lo ation ontaining a om-
plete Transparent opy of the Do ument, free of added material, whi h
the general network-using publi has a ess to download anonymously
at no harge using publi -standard network proto ols. If you use the
latter option, you must take reasonably prudent steps, when you begin
distribution of Opaque opies in quantity, to ensure that this Transpar-
ent opy will remain thus a essible at the stated lo ation until at least
one year after the last time you distribute an Opaque opy (dire tly or
through your agents or retailers) of that edition to the publi .
It is requested, but not required, that you onta t the authors of the
Do ument well before redistributing any large number of opies, to give
them a han e to provide you with an updated version of the Do ument.
4. MODIFICATIONS
You may opy and distribute a Modi ed Version of the Do ument under
the onditions of se tions 2 and 3 above, provided that you release
the Modi ed Version under pre isely this Li ense, with the Modi ed
Version lling the role of the Do ument, thus li ensing distribution and
modi ation of the Modi ed Version to whoever possesses a opy of it.
In addition, you must do these things in the Modi ed Version:
A. Use in the Title Page (and on the overs, if any) a title distin t
from that of the Do ument, and from those of previous versions
(whi h should, if there were any, be listed in the History se tion of
the Do ument). You may use the same title as a previous version
if the original publisher of that version gives permission.
282 Appendix D: GNU Free Do umentation Li ense

B. List on the Title Page, as authors, one or more persons or enti-


ties responsible for authorship of the modi ations in the Modi ed
Version, together with at least ve of the prin ipal authors of the
Do ument (all of its prin ipal authors, if it has less than ve).
C. State on the Title page the name of the publisher of the Modi ed
Version, as the publisher.
D. Preserve all the opyright noti es of the Do ument.
E. Add an appropriate opyright noti e for your modi ations adja-
ent to the other opyright noti es.
F. In lude, immediately after the opyright noti es, a li ense noti e
giving the publi permission to use the Modi ed Version under the
terms of this Li ense, in the form shown in the Addendum below.
G. Preserve in that li ense noti e the full lists of Invariant Se tions
and required Cover Texts given in the Do ument's li ense noti e.
H. In lude an unaltered opy of this Li ense.
I. Preserve the se tion entitled \History", and its title, and add to it
an item stating at least the title, year, new authors, and publisher
of the Modi ed Version as given on the Title Page. If there is no
se tion entitled \History" in the Do ument, reate one stating the
title, year, authors, and publisher of the Do ument as given on its
Title Page, then add an item des ribing the Modi ed Version as
stated in the previous senten e.
J. Preserve the network lo ation, if any, given in the Do ument for
publi a ess to a Transparent opy of the Do ument, and likewise
the network lo ations given in the Do ument for previous versions
it was based on. These may be pla ed in the \History" se tion. You
may omit a network lo ation for a work that was published at least
four years before the Do ument itself, or if the original publisher of
the version it refers to gives permission.
K. In any se tion entitled \A knowledgments" or \Dedi ations", pre-
serve the se tion's title, and preserve in the se tion all the substan e
and tone of ea h of the ontributor a knowledgments and/or dedi-
ations given therein.
L. Preserve all the Invariant Se tions of the Do ument, unaltered in
their text and in their titles. Se tion numbers or the equivalent are
not onsidered part of the se tion titles.
M. Delete any se tion entitled \Endorsements". Su h a se tion may
not be in luded in the Modi ed Version.
N. Do not retitle any existing se tion as \Endorsements" or to on i t
in title with any Invariant Se tion.
If the Modi ed Version in ludes new front-matter se tions or appendi es
that qualify as Se ondary Se tions and ontain no material opied from
the Do ument, you may at your option designate some or all of these
GNU Free Do umentation Li ense 283

se tions as invariant. To do this, add their titles to the list of Invariant


Se tions in the Modi ed Version's li ense noti e. These titles must be
distin t from any other se tion titles.
You may add a se tion entitled \Endorsements", provided it ontains
nothing but endorsements of your Modi ed Version by various parties|
for example, statements of peer review or that the text has been ap-
proved by an organization as the authoritative de nition of a standard.
You may add a passage of up to ve words as a Front-Cover Text, and a
passage of up to 25 words as a Ba k-Cover Text, to the end of the list of
Cover Texts in the Modi ed Version. Only one passage of Front-Cover
Text and one of Ba k-Cover Text may be added by (or through ar-
rangements made by) any one entity. If the Do ument already in ludes
a over text for the same over, previously added by you or by arrange-
ment made by the same entity you are a ting on behalf of, you may not
add another; but you may repla e the old one, on expli it permission
from the previous publisher that added the old one.
The author(s) and publisher(s) of the Do ument do not by this Li ense
give permission to use their names for publi ity for or to assert or imply
endorsement of any Modi ed Version.
5. COMBINING DOCUMENTS
You may ombine the Do ument with other do uments released under
this Li ense, under the terms de ned in se tion 4 above for modi ed
versions, provided that you in lude in the ombination all of the Invari-
ant Se tions of all of the original do uments, unmodi ed, and list them
all as Invariant Se tions of your ombined work in its li ense noti e.
The ombined work need only ontain one opy of this Li ense, and
multiple identi al Invariant Se tions may be repla ed with a single opy.
If there are multiple Invariant Se tions with the same name but di erent
ontents, make the title of ea h su h se tion unique by adding at the end
of it, in parentheses, the name of the original author or publisher of that
se tion if known, or else a unique number. Make the same adjustment
to the se tion titles in the list of Invariant Se tions in the li ense noti e
of the ombined work.
In the ombination, you must ombine any se tions entitled \History"
in the various original do uments, forming one se tion entitled \His-
tory"; likewise ombine any se tions entitled \A knowledgments", and
any se tions entitled \Dedi ations". You must delete all se tions enti-
tled \Endorsements."
6. COLLECTIONS OF DOCUMENTS
You may make a olle tion onsisting of the Do ument and other do u-
ments released under this Li ense, and repla e the individual opies of
this Li ense in the various do uments with a single opy that is in luded
in the olle tion, provided that you follow the rules of this Li ense for
verbatim opying of ea h of the do uments in all other respe ts.
284 Appendix D: GNU Free Do umentation Li ense

You may extra t a single do ument from su h a olle tion, and distribute
it individually under this Li ense, provided you insert a opy of this
Li ense into the extra ted do ument, and follow this Li ense in all other
respe ts regarding verbatim opying of that do ument.
7. AGGREGATION WITH INDEPENDENT WORKS
A ompilation of the Do ument or its derivatives with other separate
and independent do uments or works, in or on a volume of a storage
or distribution medium, does not as a whole ount as a Modi ed Ver-
sion of the Do ument, provided no ompilation opyright is laimed for
the ompilation. Su h a ompilation is alled an \aggregate", and this
Li ense does not apply to the other self- ontained works thus ompiled
with the Do ument, on a ount of their being thus ompiled, if they are
not themselves derivative works of the Do ument.
If the Cover Text requirement of se tion 3 is appli able to these opies
of the Do ument, then if the Do ument is less than one quarter of the
entire aggregate, the Do ument's Cover Texts may be pla ed on overs
that surround only the Do ument within the aggregate. Otherwise they
must appear on overs around the whole aggregate.
8. TRANSLATION
Translation is onsidered a kind of modi ation, so you may distribute
translations of the Do ument under the terms of se tion 4. Repla ing
Invariant Se tions with translations requires spe ial permission from
their opyright holders, but you may in lude translations of some or all
Invariant Se tions in addition to the original versions of these Invariant
Se tions. You may in lude a translation of this Li ense provided that
you also in lude the original English version of this Li ense. In ase of
a disagreement between the translation and the original English version
of this Li ense, the original English version will prevail.
9. TERMINATION
You may not opy, modify, subli ense, or distribute the Do ument ex-
ept as expressly provided for under this Li ense. Any other attempt
to opy, modify, subli ense or distribute the Do ument is void, and will
automati ally terminate your rights under this Li ense. However, par-
ties who have re eived opies, or rights, from you under this Li ense will
not have their li enses terminated so long as su h parties remain in full
omplian e.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions
of the GNU Free Do umentation Li ense from time to time. Su h
new versions will be similar in spirit to the present version, but
may di er in detail to address new problems or on erns. See
http://www.gnu.org/ opyleft/.
Ea h version of the Li ense is given a distinguishing version number.
If the Do ument spe i es that a parti ular numbered version of this
GNU Free Do umentation Li ense 285

Li ense \or any later version" applies to it, you have the option of
following the terms and onditions either of that spe i ed version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Do ument does not spe ify a version
number of this Li ense, you may hoose any version ever published (not
as a draft) by the Free Software Foundation.
286 Appendix D: GNU Free Do umentation Li ense
Index 287

Index
% Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . 12
% (remainder fun tion) . . . . . . . . . . . . . . 258 Arguments' data types . . . . . . . . . . . . . . . 13
Arguments, variable number of . . . . . . . . 14
Asterisk for read-only bu er . . . . . . . . . . 65
( Auto Fill mode turned on . . . . . . . . . . . 218
autoload . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
(debug) in ode . . . . . . . . . . . . . . . . . . . . 235 Automati mode sele tion . . . . . . . . . . . 218
Axis, print horizontal . . . . . . . . . . . . . . . 263
* Axis, print verti al . . . . . . . . . . . . . . . . . . 256
* (multipli ation) . . . . . . . . . . . . . . . . . . . . 31
* for read-only bu er . . . . . . . . . . . . . . . . . 65 B
`*s rat h*' bu er . . . . . . . . . . . . . . . . . . 123 beginning-of-buffer . . . . . . . . . . . . . . . . 69
`bind' de ned . . . . . . . . . . . . . . . . . . . . . . . 17
. `body' de ned . . . . . . . . . . . . . . . . . . . . . . . 30
Body of graph . . . . . . . . . . . . . . . . . . . . . . 203
`.ema s' le . . . . . . . . . . . . . . . . . . . . . . . . 213 Bu er size . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
`.ema s' le, beginning of . . . . . . . . . . . 216 Bu er, history of word . . . . . . . . . . . . . . . 24
buffer-file-name . . . . . . . . . . . . . . . . . . . 23
/ buffer-menu, bound to key . . . . . . . . . 221
buffer-name . . . . . . . . . . . . . . . . . . . . . . . . 23
/ (division) . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Bug, most insidious type . . . . . . . . . . . . 274
Building robots . . . . . . . . . . . . . . . . . . . . . 134
Building Tags in the Ema s sour es . . 164
> Byte ompiling . . . . . . . . . . . . . . . . . . . . . . . 8
> (greater than) . . . . . . . . . . . . . . . . . . . . 40

<
C
C language primitives . . . . . . . . . . . . . . . . 29
<= (less than or equal) . . . . . . . . . . . . . . 127 C, a digression into . . . . . . . . . . . . . . . . . . 98
` all' de ned . . . . . . . . . . . . . . . . . . . . . . . 27
an el-debug-on-entry . . . . . . . . . . . . . 234
A ar, introdu ed . . . . . . . . . . . . . . . . . . . . . 81
A umulate, type of re ursive pattern dr, introdu ed . . . . . . . . . . . . . . . . . . . . . 81
............................... 142 Changing a fun tion de nition . . . . . . . . 32
add-hook . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Chest of Drawers, metaphor for a symbol
and . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108, 156 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
and, introdu ed . . . . . . . . . . . . . . . . . . . . 108 Clipping text . . . . . . . . . . . . . . . . . . . . . . . . 89
Anonymous fun tion . . . . . . . . . . . . . . . . 272 Code installation . . . . . . . . . . . . . . . . . . . . 36
append-to-buffer . . . . . . . . . . . . . . . . . . . 56 ` ommand' de ned . . . . . . . . . . . . . . . . . . . . 23
apply . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 Comments in Lisp ode . . . . . . . . . . . . . . 32
apropos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 Common Lisp . . . . . . . . . . . . . . . . . . . . . . . xiii
Argument as lo al variable . . . . . . . . . . 131 ompare-windows . . . . . . . . . . . . . . . . . . . 220
`argument' de ned . . . . . . . . . . . . . . . . . . . 12 on at . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
`argument list' de ned . . . . . . . . . . . . . . 30 ond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Argument, wrong type of . . . . . . . . . . . . . 14 ondition- ase . . . . . . . . . . . . . . . . . . . . . 95
288 Index

Conditional 'twixt two versions of Ema s E


. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
edebug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
Conditional with if . . . . . . . . . . . . . . . . . . 39 edit-options . . . . . . . . . . . . . . . . . . . . . . 101
ons, example . . . . . . . . . . . . . . . . . . . . . . 107 Else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
ons, introdu ed . . . . . . . . . . . . . . . . . . . . 83 Ema s version, hoosing . . . . . . . . . . . . . 225
opy-region-as-kill . . . . . . . . . . . . . . . 102 `empty list' de ned . . . . . . . . . . . . . . . . . . 2
opy-to-buffer . . . . . . . . . . . . . . . . . . . . . 63 `empty string' de ned . . . . . . . . . . . . . . . 48
Count words re ursively . . . . . . . . . . . . . 173 eobp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
ount-words-in-defun . . . . . . . . . . . . . . 185 eq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
ount-words-region . . . . . . . . . . . . . . . . 167 eq (example of use) . . . . . . . . . . . . . . . . . 104
Counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 equal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Counting words in a defun . . . . . . 181, 183 Erasing text . . . . . . . . . . . . . . . . . . . . . . . . . 89
urrent-buffer . . . . . . . . . . . . . . . . . . . . . 25 error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Customizing your `.ema s' le . . . . . . . 213 Error for symbol without fun tion . . . . . 11
Cutting and storing text . . . . . . . . . . . . . . 89 Error for symbol without value . . . . . . . 11
Error message generation . . . . . . . . . . . . . . 4
etags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
D `evaluate' de ned . . . . . . . . . . . . . . . . . . . . 4
Data types . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Evaluating inner lists . . . . . . . . . . . . . . . . . . 9
debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Evaluation pra ti e . . . . . . . . . . . . . . . . . . 23
debug-on-entry . . . . . . . . . . . . . . . . . . . . 232
Every, type of re ursive pattern . . . . . . 141
debug-on-quit . . . . . . . . . . . . . . . . . . . . . 234
Example variable, fill- olumn . . . . . . . 10
debugging . . . . . . . . . . . . . . . . . . . . . . . . . . 231 `expression' de ned . . . . . . . . . . . . . . . . . . 2
default-mode-line-format . . . . . . . . . 228
`default.el' init le . . . . . . . . . . . . . . . . 213
def ustom . . . . . . . . . . . . . . . . . . . . . . . . . 214
Deferment in re ursion . . . . . . . . . . . . . . 143
F
Falsehood and truth in Ema s Lisp . . . . 43
Defermentless solution . . . . . . . . . . . . . . 145
FDL, GNU Free Do umentation Li ense
De nition installation . . . . . . . . . . . . . . . . 31 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
De nition writing . . . . . . . . . . . . . . . . . . . . 29 files-in-below-dire tory . . . . . . . . . 194
De nition, how to hange . . . . . . . . . . . . . 32 fill- olumn, an example variable . . . . 10
defun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Find a File . . . . . . . . . . . . . . . . . . . . . . . . . 187
defvar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Find fun tion do umentation . . . . . . . . . 51
defvar for a user ustomizable variable Find sour e of fun tion . . . . . . . . . . . . . . . 51
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
find-tags . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
defvar with an asterisk . . . . . . . . . . . . . 101 Flowers in a eld . . . . . . . . . . . . . . . . . . . . . 1
delete-and-extra t-region . . . . . . 96, 98 Fo using attention (narrowing) . . . . . . . 77
Deleting text . . . . . . . . . . . . . . . . . . . . . . . . 89 `form' de ned . . . . . . . . . . . . . . . . . . . . . . . . . 2
des ribe-fun tion . . . . . . . . . . . . . . . . . . 53 Formatting onvention . . . . . . . . . . . . . . . 58
des ribe-fun tion, introdu ed . . . . . . 51 Formatting help . . . . . . . . . . . . . . . . . . . . . . 3
Digression into C . . . . . . . . . . . . . . . . . . . . 98 forward-paragraph . . . . . . . . . . . . . . . . . 155
dire tory-files . . . . . . . . . . . . . . . . . . . 194 forward-senten e . . . . . . . . . . . . . . . . . . 151
Division . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 `fun tion' de ned . . . . . . . . . . . . . . . . . . 5, 6
dolist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 `fun tion definition' de ned . . . . . . . . 29
dotimes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Fun tion de nition installation . . . . . . . . 31
Drawers, Chest of, metaphor for a symbol Fun tion de nition writing . . . . . . . . . . . 29
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Fun tion de nition, how to hange . . . . 32
Dupli ated words fun tion . . . . . . . . . . . 241 Fun tions, primitive . . . . . . . . . . . . . . . . . . 29
Index 289

G kill-new . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Generate an error message . . . . . . . . . . . . . 4 kill-region . . . . . . . . . . . . . . . . . . . . . . . . 94
Getting a bu er . . . . . . . . . . . . . . . . . . . . . 25 Killing text . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Global set key . . . . . . . . . . . . . . . . . . . . . . 220
global-set-key . . . . . . . . . . . . . . . . . . . . 220
global-unset-key . . . . . . . . . . . . . . . . . . 221
L
Graph prototype . . . . . . . . . . . . . . . . . . . . 203 lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
Graph, printing all . . . . . . . . . . . . . . . . . . 267 length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
graph-body-print . . . . . . . . . . . . . . . . . . 208 lengths-list-file . . . . . . . . . . . . . . . . . 188
graph-body-print Final version. . . . . . 268 lengths-list-many-files . . . . . . . . . . 190
let . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
let expression sample . . . . . . . . . . . . . . . . 38
H let expression, parts of . . . . . . . . . . . . . . 37
Handling the kill ring . . . . . . . . . . . . . . . 243 let variables uninitialized . . . . . . . . . . . . 39
Help typing lists . . . . . . . . . . . . . . . . . . . . . . 3 Library, as term for ` le' . . . . . . . . . . . . . 52
Horizontal axis printing . . . . . . . . . . . . . 263 line-to-top-of-window . . . . . . . . . . . . . 224
Lisp Atoms . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Lisp history . . . . . . . . . . . . . . . . . . . . . . . . xiii
I Lisp interpreter, explained . . . . . . . . . . . . . 4
if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Lisp interpreter, what it does . . . . . . . . . . 7
`if-part' de ned . . . . . . . . . . . . . . . . . . . . 40 Lisp Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
indent-tabs-mode . . . . . . . . . . . . . . . . . . 219 Lisp ma ro . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Indentation for formatting . . . . . . . . . . . . 58 list-buffers, rebound . . . . . . . . . . . . . 221
Initialization le . . . . . . . . . . . . . . . . . . . . 213 Lists in a omputer . . . . . . . . . . . . . . . . . 113
Initializing a variable . . . . . . . . . . . . . . . . 100 load-library . . . . . . . . . . . . . . . . . . . . . . 223
Inner list evaluation . . . . . . . . . . . . . . . . . . . 9 load-path . . . . . . . . . . . . . . . . . . . . . . . . . 223
insert-buffer . . . . . . . . . . . . . . . . . . . . . . 64 Loading les . . . . . . . . . . . . . . . . . . . . . . . . 222
insert-buffer-substring . . . . . . . . . . . 56 `lo al variable' de ned . . . . . . . . . . . . . 37
Insidious type of bug . . . . . . . . . . . . . . . . 274 Lo al variables list, per-bu er, . . . . . . . 218
Install a Fun tion De nition . . . . . . . . . . 31 Lo ation of point . . . . . . . . . . . . . . . . . . . . 27
Install ode permanently . . . . . . . . . . . . . 36 looking-at . . . . . . . . . . . . . . . . . . . . . . . . 159
intera tive . . . . . . . . . . . . . . . . . . . . . . . . 33 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
`intera tive fun tion' de ned . . . . . . . 23 Loops and re ursion . . . . . . . . . . . . . . . . . 121
Intera tive fun tions . . . . . . . . . . . . . . . . . 33
Intera tive options . . . . . . . . . . . . . . . . . . . 35
intera tive, example use of . . . . . . . . . 65 M
Interpreter, Lisp, explained . . . . . . . . . . . . 4 Ma lisp . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
Interpreter, what it does . . . . . . . . . . . . . . . 7 Ma ro, lisp . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Mail aliases . . . . . . . . . . . . . . . . . . . . . . . . 219
make tags . . . . . . . . . . . . . . . . . . . . . . . . . . 164
K make-string . . . . . . . . . . . . . . . . . . . . . . . 261
Keep, type of re ursive pattern . . . . . . 143 map ar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
Key setting globally . . . . . . . . . . . . . . . . . 220 mark . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Key unbinding . . . . . . . . . . . . . . . . . . . . . . 221 mark-whole-buffer . . . . . . . . . . . . . . . . . . 54
Keymaps . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 mat h-beginning . . . . . . . . . . . . . . . . . . . 161
Keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 max . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Kill ring handling . . . . . . . . . . . . . . . . . . . 243 message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Kill ring overview . . . . . . . . . . . . . . . . . . . 117 min . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
kill-append . . . . . . . . . . . . . . . . . . . . . . . 104 Mode line format . . . . . . . . . . . . . . . . . . . 228
290 Index

Mode sele tion, automati . . . . . . . . . . . 218 print-X-axis . . . . . . . . . . . . . . . . . . . . . . 266


Motion by senten e and paragraph . . . 149 print-X-axis-numbered-line . . . . . . . 265
print-X-axis-ti -line . . . . . . . . . . . . . 265
N print-Y-axis . . . . . . . . . . . . . . . . . . . . . .
Printing the whole graph . . . . . . . . . . . . 267
262
Narrowing . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
prog1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
`narrowing' de ned . . . . . . . . . . . . . . . . . . 28
nil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 progn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
nil, history of word . . . . . . . . . . . . . . . . . . 24 Program, running one . . . . . . . . . . . . . . . . . 4
No deferment solution . . . . . . . . . . . . . . . 145 Prototype graph . . . . . . . . . . . . . . . . . . . . 203
nreverse . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
nth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
nth dr . . . . . . . . . . . . . . . . . . . . . . . . . 85, 102
nth dr, example . . . . . . . . . . . . . . . . . . . 107 R
number-to-string . . . . . . . . . . . . . . . . . . 259 re-sear h-forward . . . . . . . . . . . . . . . . . 150
Read-only bu er . . . . . . . . . . . . . . . . . . . . . 65
O Readying a graph . . . . . . . . . . . . . . . . . . . 203
Rebinding keys . . . . . . . . . . . . . . . . . . . . . 221
o ur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
optional . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 Re ursion . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Optional arguments . . . . . . . . . . . . . . . . . . 70 Re ursion and loops . . . . . . . . . . . . . . . . . 121
Options for intera tive . . . . . . . . . . . . . 35 Re ursion without Deferments . . . . . . . 143
or . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Re ursive De nition Parts . . . . . . . . . . . 135
other-buffer . . . . . . . . . . . . . . . . . . . . . . . 25 Re ursive pattern: a umulate . . . . . . . 142
Re ursive pattern: every . . . . . . . . . . . . 141
P Re ursive pattern: keep . . . . . . . . . . . . . 143
Paragraphs, movement by . . . . . . . . . . . 149 Re ursive Patterns . . . . . . . . . . . . . . . . . . 140
Parts of a Re ursive De nition . . . . . . . 135 re ursive- ount-words . . . . . . . . . . . . . 178
Parts of let expression . . . . . . . . . . . . . . . 37 re ursive-graph-body-print . . . . . . . 210
Passing information to fun tions . . . . . . 12 re ursive-lengths-list-many-files
Pasting text . . . . . . . . . . . . . . . . . . . . . . . . 117 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Patterns, sear hing for . . . . . . . . . . . . . . 149 Re ursively ounting words . . . . . . . . . . 173
Per-bu er, lo al variables list . . . . . . . . 218 regexp-quote . . . . . . . . . . . . . . . . . . . . . . 157
Permanent ode installation . . . . . . . . . . 36 Region, what it is . . . . . . . . . . . . . . . . . . . . 44
point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
`point' de ned . . . . . . . . . . . . . . . . . . . . . . 27 Regular expression sear hes . . . . . . . . . . 149
Point lo ation . . . . . . . . . . . . . . . . . . . . . . . 27 Regular expressions for word ounting
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Point, mark, bu er preservation . . . . . . . 44
Pra ti ing evaluation . . . . . . . . . . . . . . . . . 23 Remainder fun tion, % . . . . . . . . . . . . . . . 258
Preserving point, mark, and bu er . . . . 44 Repetition (loops) . . . . . . . . . . . . . . . . . . 121
Primitive fun tions . . . . . . . . . . . . . . . . . . . 29 Repetition for word ounting . . . . . . . . 167
Primitives written in C . . . . . . . . . . . . . . . 29 Retrieving text . . . . . . . . . . . . . . . . . . . . . 117
Print horizontal axis . . . . . . . . . . . . . . . . 263 reverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Print verti al axis . . . . . . . . . . . . . . . . . . . 256
print-elements-of-list . . . . . . . . . . . 123
Ring, making a list like a . . . . . . . . . . . . 243
print-elements-re ursively . . . . . . . 136 Robots, building . . . . . . . . . . . . . . . . . . . . 134
print-graph Final version. . . . . . . . . . . 269 rotate-yank-pointer . . . . . . . . . . 117, 243
print-graph varlist . . . . . . . . . . . . . . . . . 256 Run a program . . . . . . . . . . . . . . . . . . . . . . . 4
Index 291

S top-of-ranges . . . . . . . . . . . . . . . . . . . . . 198
Sample let expression . . . . . . . . . . . . . . . 38 triangle-bugged . . . . . . . . . . . . . . . . . . . 231
save-ex ursion . . . . . . . . . . . . . . . . . . . . . 44 triangle-re ursively . . . . . . . . . . . . . . 137
save-restri tion . . . . . . . . . . . . . . . . . . . 77 Truth and falsehood in Ema s Lisp . . . . 43
sear h-forward . . . . . . . . . . . . . . . . . . . . . 92 Types of data . . . . . . . . . . . . . . . . . . . . . . . 13
Sear hes, illustrating . . . . . . . . . . . . . . . . 149
senten e-end . . . . . . . . . . . . . . . . . . . . . . 149
Senten es, movement by . . . . . . . . . . . . . 149
U
set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Unbinding key . . . . . . . . . . . . . . . . . . . . . . 221
set-buffer . . . . . . . . . . . . . . . . . . . . . . . . . 26 Uninitialized let variables . . . . . . . . . . . . 39
set ar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
set dr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
set dr, example . . . . . . . . . . . . . . . . . . . 107
V
setq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Variable initialization . . . . . . . . . . . . . . . 100
Setting a key globally . . . . . . . . . . . . . . . 220 Variable number of arguments . . . . . . . . 14
Setting value of variable . . . . . . . . . . . . . . 17 Variable, example of, fill- olumn . . . . 10
`side effe t' de ned . . . . . . . . . . . . . . . . . 8 Variable, setting value . . . . . . . . . . . . . . . . 17
Simple extension in `.ema s' le . . . . . 224 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
simplified-beginning-of-buffer . . . . 52 `varlist' de ned . . . . . . . . . . . . . . . . . . . . 37
`site-init.el' init le . . . . . . . . . . . . . . 213 Version of Ema s, hoosing . . . . . . . . . . 225
`site-load.el' init le . . . . . . . . . . . . . . 213 Verti al axis printing . . . . . . . . . . . . . . . . 256
Size of bu er . . . . . . . . . . . . . . . . . . . . . . . . 27
Solution without deferment . . . . . . . . . . 145
sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 W
Sour e level debugger . . . . . . . . . . . . . . . 235 what-line . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Spe ial form . . . . . . . . . . . . . . . . . . . . . . . . . . 7 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Spe ial form of defun . . . . . . . . . . . . . . . . 29 Whitespa e in lists . . . . . . . . . . . . . . . . . . . . 3
Storing and utting text . . . . . . . . . . . . . . 89 Whole graph printing . . . . . . . . . . . . . . . 267
`string' de ned . . . . . . . . . . . . . . . . . . . . . . 3 Widening . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
swit h-to-buffer . . . . . . . . . . . . . . . . . . . 26 Widening, example of . . . . . . . . . . . . . . . . 78
Swit hing to a bu er . . . . . . . . . . . . . . . . . 26 Word ounting in a defun . . . . . . . . . . . 181
Symbol names . . . . . . . . . . . . . . . . . . . . . . . . 6 Words and symbols in defun . . . . . . . . . 181
Symbol without fun tion error . . . . . . . . 11 Words, ounted re ursively . . . . . . . . . . 173
Symbol without value error . . . . . . . . . . . 11 Words, dupli ated . . . . . . . . . . . . . . . . . . 241
Symboli expressions, introdu ed . . . . . . . 2 Writing a fun tion de nition . . . . . . . . . . 29
Symbols as a Chest of Drawers . . . . . . . 115 Wrong type of argument . . . . . . . . . . . . . . 14
Syntax ategories and tables . . . . . . . . . 182
X
T X axis printing . . . . . . . . . . . . . . . . . . . . . 263
Tabs, preventing . . . . . . . . . . . . . . . . . . . . 219 X-axis-element . . . . . . . . . . . . . . . . . . . . 265
`TAGS' le, reate own . . . . . . . . . . . . . . . 163
Tags in the Ema s sour es . . . . . . . . . . . 164
TAGS table, spe ifying . . . . . . . . . . . . . . . 51 Y
Text between double quotation marks . . 3 Y axis printing . . . . . . . . . . . . . . . . . . . . . 256
Text Mode turned on . . . . . . . . . . . . . . . 218 Y-axis- olumn . . . . . . . . . . . . . . . . . . . . . 261
Text retrieval . . . . . . . . . . . . . . . . . . . . . . . 117 Y-axis- olumn Final version. . . . . . . . . 268
the-the . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Y-axis-label-spa ing . . . . . . . . . . . . . . 259
`then-part' de ned . . . . . . . . . . . . . . . . . . 40 Y-axis-ti . . . . . . . . . . . . . . . . . . . . . . . .260
292 Index

yank .......................... 117, 249 Z


zap-to- har . . . . . . . . . . . . . . . . . . . . . . . . 90
yank-pop . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 zerop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
About the Author

Robert J. Chassell has worked with GNU Ema s sin e 1985. He


writes and edits, tea hes Ema s and Ema s Lisp, and speaks
throughout the world on software freedom. Chassell was a found-
ing Dire tor and Treasurer of the Free Software Foundation, In .
He is o-author of the Texinfo manual, and has edited more than
a dozen other books. He graduated from Cambridge University, in
England. He has an abiding interest in so ial and e onomi history
and ies his own airplane.

You might also like