Lisp Users and V endo rs Conference August 10, 1993 T uto - - PDF document

lisp users and v endo rs conference august 10 1993 t uto
SMART_READER_LITE
LIVE PREVIEW

Lisp Users and V endo rs Conference August 10, 1993 T uto - - PDF document

Lisp Users and V endo rs Conference August 10, 1993 T uto rial on Go o d Lisp Programming St yle P eter No rvig Sun Microsystems Labs Inc. Kent Pitman Ha rlequin, Inc. P o rtions cop yright c 1992, 1993


slide-1
SLIDE 1 Lisp Users and V endo rs Conference August 10, 1993 T uto rial
  • n
Go
  • d
Lisp Programming St yle P eter No rvig Sun Microsystems Labs Inc. Kent Pitman Ha rlequin, Inc. P
  • rtions
cop yright c
  • 1992,
1993 P eter No rvig. P
  • rtions
cop yright c
  • 1992,
1993 Kent M. Pitman. All Rights Reserved. 1
slide-2
SLIDE 2 Outline 1. What is Go
  • d
St yle? 2. Tips
  • n
Built-In F unctionalit y 3. Tips
  • n
Nea r-Standa rd T
  • ls
4. Kinds
  • f
Abstraction 5. Programming in the La rge 6. Miscellaneous 2
slide-3
SLIDE 3 1. What is Go
  • d
St yle? Go
  • d
Lisp Programming St yle \Elegance is not
  • ptional."
{ Richa rd A. O'Keefe Go
  • d
st yle (in any language) leads to p rograms that a re:
  • Understandable
  • Reusable
  • Extensible
  • Ecient
  • Easy
to develop/debug It also helps co rrectness, robustness, compatibil i t y Our maxims
  • f
go
  • d
st yle a re:
  • Be
explicit
  • Be
sp ecic
  • Be
concise
  • Be
consistent
  • Be
helpful (anticipate the reader's needs)
  • Be
conventional (don't b e
  • bscure)
  • Build
abstractions at a usable level
  • Allo
w to
  • ls
to interact (referential transpa rency) Go
  • d
st yle is the \underw a re" that supp
  • rts
a p rogram 3
slide-4
SLIDE 4 1.1. Where do es go
  • d
st yle come from? What T
  • Believe
Don't b elieve everything w e tell y
  • u.
(Just most.) W
  • rry
less ab
  • ut
what to b elieve and mo re ab
  • ut
why. Kno w where y
  • ur
\St yle Rules" come from:
  • Religion,
Go
  • d
vs. Evil \This w a y is b etter."
  • Philosophy
\This is consistent with
  • ther
things."
  • Robustness,
Liabilit y , Safet y , Ethics \I'll put in redundant checks to avoid something ho rrible."
  • Legalit
y \Our la wy ers sa y do it this w a y ."
  • P
ersonalit y , Opinion \I lik e it this w a y ."
  • Compatibilit
y \Another to
  • l
exp ects this w a y ."
  • P
  • rtabilit
y \Other compilers p refer this w a y ."
  • Co
  • p
eration, Convention \It has to b e done some unifo rm w a y , so w e agreed
  • n
this
  • ne."
  • Habit,
T radition \W e've alw a ys done it this w a y ."
  • Abilit
y \My p rogrammers a ren't sophisticated enough."
  • Memo
ry \Kno wing ho w I w
  • uld
do it means I don't have to rememb er ho w I did do it."
  • Sup
erstition \I'm sca red to do it dierently ."
  • Practicalit
y \This mak es
  • ther
things easier." 4
slide-5
SLIDE 5 1.1. Where do es go
  • d
st yle come from? It's All Ab
  • ut
Communication Exp ression + Understanding = Communication Programs communicate with:
  • Human
readers
  • Compilers
  • T
ext edito rs (a rglist, do c string, indent)
  • T
  • ls
(trace, step, ap rop
  • s,
xref, manual)
  • Users
  • f
the p rogram (indirect communication) 5
slide-6
SLIDE 6 1.1. Where do es go
  • d
st yle come from? Kno w the Context When reading co de:
  • Kno
w who wrote it and when. When writing co de:
  • Annotate
it with comments.
  • Sign
and date y
  • ur
comments! (Should b e an edito r command to do this) Some things to notice:
  • P
eople's st yle changes
  • ver
time.
  • The
same p erson at dierent times can seem lik e a dierent p erson.
  • Sometimes
that p erson is y
  • u.
6
slide-7
SLIDE 7 1.2. Ho w do I kno w if it's go
  • d?
V alue Systems Are Not Absolute St yle rules cannot b e view ed in isolation. They
  • ften
  • verlap
in conicting w a ys. The fact that st yle rules conict with
  • ne
another re- ects the natural fact that real-w
  • rld
goals conict. A go
  • d
p rogrammer mak es trade-os in p rogrammi ng st yle that reect underlying p rio rit y choices among va r- ious majo r goals:
  • Understandable
  • Reusable
  • Extensible
  • Ecient
(co ding, space, sp eed, ...)
  • Easy
to develop/debug 7
slide-8
SLIDE 8 1.2. Ho w do I kno w if it's go
  • d?
Why Go
  • d
St yle is Go
  • d
Go
  • d
st yle helps build the current p rogram, and the next
  • ne:
  • Organizes
a p rogram, relieving human memo ry needs
  • Encourages
mo dula r, reusable pa rts St yle is not just added at the end. It pla ys a pa rt in:
  • Organization
  • f
the p rogram into les
  • T
  • p-level
design, structure and la y
  • ut
  • f
each le
  • Decomp
  • sition
into mo dules and comp
  • nents
  • Data-structure
choice
  • Individual
function design/implem entation
  • Naming,
fo rmatting, and do cumenting standa rds 8
slide-9
SLIDE 9 1.2. Ho w do I kno w if it's go
  • d?
Why St yle is Practical: Memo ry \When I w as y
  • ung,
I could imagine a castle with t w ent y ro
  • ms
with each ro
  • m
having ten dierent
  • b-
jects in it. I w
  • uld
have no p roblem. I can't do that anymo re. No w I think mo re in terms
  • f
ea rlier exp eri- ences. I see a net w
  • rk
  • f
inchoate clouds, instead
  • f
the picture-p
  • stca
rd clea rness. But I do write b etter p rograms." { Cha rles Simonyi \Some p eople a re go
  • d
p rogrammers b ecause they can handle many mo re details than most p eople. But there a re a lot
  • f
disadvantages in selecting p rogrammers fo r that reason|it can result in p rograms no
  • n
else can maintai n." { Butler Lampson \Pick
  • ut
any three lines in my p rogram, and I can tell y
  • u
where they're from and what they do." { David McDonald Go
  • d
st yle replaces the need fo r great memo ry:
  • Mak
e sure any 3 (5? 10?) lines a re self-explanato ry Also called \referential transpa rency" P ack age complexit y into
  • bjects
and abstractions; not global va riables/dep endencies
  • Mak
e it \fractally" self-o rganizing all the w a y up/do wn
  • Sa
y what y
  • u
mean
  • Mean
what y
  • u
sa y 9
slide-10
SLIDE 10 1.2. Ho w do I kno w if it's go
  • d?
Why St yle is Practical: Reuse Structured Programmi ng encourages mo dules that meet sp ecications and can b e reused within the b
  • unds
  • f
that sp ecication. Stratied Design encourages mo dules with commonly- needed functionalit y , which can b e reused even when the sp ecication changes,
  • r
in another p rogram. Object-Oriented Design is stratied design that con- centrates
  • n
classes
  • f
  • bjects
and
  • n
info rmation hid- ing. Y
  • u
should aim to reuse:
  • Data
t yp es (classes)
  • F
unctions (metho ds)
  • Control
abstractions
  • Interface
abstractions (pack ages, mo dules)
  • Syntactic
abstractions (macros and whole languages) 10
slide-11
SLIDE 11 1.2. Ho w do I kno w if it's go
  • d?
Sa y What Y
  • u
Mean \Sa y what y
  • u
mean, simply and directly ." { Kernighan & Plauger Sa y what y
  • u
mean in data (b e sp ecic, concise):
  • Use
data abstractions
  • Dene
languages fo r data, if needed
  • Cho
  • se
names wisely Sa y what y
  • u
mean in co de (b e concise, conventional):
  • Dene
interfaces clea rly
  • Use
Macros and languages app rop riatel y
  • Use
built-in functions
  • Create
y
  • ur
  • wn
abstractions
  • Don't
do it t wice if y
  • u
can do it
  • nce
In annotations (b e explicit, helpful):
  • Use
app rop riate detail fo r comments
  • Do
cumentation strings a re b etter than comments
  • Sa
y what it is fo r, not just what it do es
  • Decla
rations and assertions
  • Systems
(and test les, etc.) 11
slide-12
SLIDE 12 1.2. Ho w do I kno w if it's go
  • d?
Be Explicit Optional and Keyw
  • rd
a rguments. If y
  • u
have to lo
  • k
up the default value, y
  • u
need to supply it. Y
  • u
should
  • nly
tak e the default if y
  • u
truly b elieve y
  • u
don't ca re
  • r
if y
  • u're
sure the default is w ell-understo
  • d
and w ell-accepted b y all. F
  • r
example, when
  • p
ening a le, y
  • u
should almost never consider
  • mitting
the :direction k eyw
  • rd
a rgu- ment, even though y
  • u
kno w it will default to :input. Decla rations. If y
  • u
kno w t yp e info rmation, decla re it. Don't do what some p eople do and
  • nly
decla re things y
  • u
kno w the compiler will use. Compilers change, and y
  • u
w ant y
  • ur
p rogram to naturally tak e advantage
  • f
those changes without the need fo r
  • ngoing
intervention. Also, decla rations a re fo r communication with human readers, to
  • {not
just compilers. Comments. If y
  • u're
thinking
  • f
something useful that
  • thers
might w ant to kno w when they read y
  • ur
co de and that might not b e instantly appa rent to them, mak e it a comment. 12
slide-13
SLIDE 13 1.2. Ho w do I kno w if it's go
  • d?
Be Sp ecic Be as sp ecic as y
  • ur
data abstractions w a rrant, but no mo re. Cho
  • se:
;; more specific ;; more abstract (mapc #'process
  • wo
rd (map nil #'process- wo rd (first sentences) ) (elt sentences 0)) Most sp ecic conditional:
  • if
fo r t w
  • -b
ranch exp ression
  • when,
unless fo r
  • ne-b
ranch statement
  • and,
  • r
fo r b
  • lean
value
  • nly
  • cond
fo r multi-b ranch statement
  • r
exp ression ;; Violates Expectat ion : ;; Follows Expectat io n: (and (numberp x) (cos x)) (and (numberp x) (> x 3)) (if (numberp x) (cos x)) (if (numberp x) (cos x) nil) (if (numberp x) (print x)) (when (numberp x) (print x)) 13
slide-14
SLIDE 14 1.2. Ho w do I kno w if it's go
  • d?
Be Concise T est fo r the simplest case. If y
  • u
mak e the same test (o r return the same result) in t w
  • places,
there must b e an easier w a y . Bad: verb
  • se,
convoluted (defun count-al l-n um ber s (alist) (cond ((null alist) 0) (t (+ (if (listp (first alist)) (count-a ll- nu mbe rs (first alist)) (if (numberp (first alist)) 1 0)) (count-a ll- nu mb ers (rest alist)) )) ))
  • Returns
t wice
  • Nonstanda
rd indentation
  • alist
suggests asso ciation list Go
  • d:
(defun count-al l-n um ber s (exp) (typecas e exp (cons (+ (count-all
  • nu
mb er s (first exp)) (count-all
  • nu
mb er s (rest exp)))) (number 1) (t 0))) cond instead
  • f
typecase is equally go
  • d
(less sp ecic, mo re conventional, consistent). 14
slide-15
SLIDE 15 1.2. Ho w do I kno w if it's go
  • d?
Be Concise Maximize LOCNW: lines
  • f
co de not written. \Sho rter is b etter and sho rtest is b est." { Jim Meehan Bad: to
  • verb
  • se,
inecient (defun vector-a dd (x y) (let ((z nil) n) (setq n (min (list-le ngt h x) (list-len gth y))) (dotimes (j n (reverse z)) (setq z (cons (+ (nth j x) (nth j y)) z))))) (defun matrix-a dd (A B) (let ((C nil) m) (setq m (min (list-le ngt h A) (list-len gth B))) (dotimes (i m (reverse C)) (setq C (cons (vector-ad d (nth i A) (nth i B)) C)))))
  • Use
  • f
nth mak es this O (n 2 )
  • Why
list-len gth ? Why not length
  • r
mapcar?
  • Why
not nreverse ?
  • Why
not use a rra ys to implement a rra ys?
  • The
return value is hidden 15
slide-16
SLIDE 16 1.2. Ho w do I kno w if it's go
  • d?
Be Concise Better: mo re concise (defun vector-a dd (x y) "Element
  • wi
se add
  • f
two vectors" (mapcar #'+ x y)) (defun matrix-a dd (A B) "Element
  • wi
se add
  • f
two matrices (lists
  • f
lists)" (mapcar #'vector-a dd A B)) Or use generic functions: (defun add (&rest args) "Generic addition" (if (null args) (reduce #'binary- ad d args))) (defmeth
  • d
binary-ad d ((x number) (y number)) (+ x y)) (defmeth
  • d
binary-ad d ((x sequence) (y sequence )) (map (type-of x) #'binary- ad d x y)) 16
slide-17
SLIDE 17 1.2. Ho w do I kno w if it's go
  • d?
Be Helpful Do cumentation should b e
  • rganized
a round tasks the user needs to do, not a round what y
  • ur
p rogram hap- p ens to p rovide. Adding do cumentation strings to each function usually do esn't tell the reader ho w to use y
  • ur
p rogram, but hints in the right place can b e very ef- fective. Go
  • d:
(from Gnu Emacs
  • nline
help) next-lin e: Move curso r vertically do wn ARG lines. : : : If y
  • u
a re thinking
  • f
using this in a Lisp p rogram, consider using `fo rw a rd-line' instead. It is usually eas- ier to use and mo re reliable (no dep endence
  • n
goal column, etc.). defun: denes NAME as a function. The denition is (lambda ARGLIST [DOCSTRIN G] BODY...). See also the function interactiv e. These anticipate user's use and p roblems. 17
slide-18
SLIDE 18 1.2. Ho w do I kno w if it's go
  • d?
Be Conventional Build y
  • ur
  • wn
functionalit y to pa rallel existing features Ob ey naming conventions: with-somethi ng, dosomething macros Use built-in functionalit y when p
  • ssible
  • Conventional:
reader will kno w what y
  • u
mean
  • Concise:
reader do esn't have to pa rse the co de
  • Ecient:
has b een w
  • rk
ed
  • n
heavily Bad: non-conventional (defun add-to-l ist (elt list) (cond ((member elt lst) lst) (t (cons elt lst)))) Go
  • d:
use a built-in function (left as an exercise) \Use lib ra ry functions" { Kernighan & Plauger 18
slide-19
SLIDE 19 1.2. Ho w do I kno w if it's go
  • d?
Be Consistent Some pairs
  • f
  • p
erato rs have
  • verlapping
capabiliti es. Be consistent ab
  • ut
which y
  • u
use in neutral cases (where either can b e used), so that it is appa rent when y
  • u're
doing something unusual. Here a re examples involving let and let*. The rst exploits pa rallel binding and the second sequential. The third is neutral. (let ((a b) (b a)) ...) (let* ((a b) (b (* 2 a)) (c (+ b 1))) ...) (let ((a (* x (+ 2 y))) (b (* y (+ 2 x)))) ...) Here a re analogous examples using flet and labels. The rst exploits closure
  • ver
the lo cal function, the second exploits non-closure. The third is neutral. (labels ((process (x) ... (process (cdr x)) ...)) ...) (flet ((foo (x) (+ (foo x) 1))) ...) (flet ((add3 (x) (+ x 3))) ...) In b
  • th
cases, y
  • u
could cho
  • se
things the
  • ther
w a y a round, alw a ys using let*
  • r
labels in the neutral case, and let
  • r
flet in the unusual case. Consistency mat- ters mo re than the actual choice. Most p eople, ho w- ever, think
  • f
let and flet as the no rmal choices. 19
slide-20
SLIDE 20 1.2. Ho w do I kno w if it's go
  • d?
Cho
  • se
the Right Language Cho
  • se
the app rop riate language, and use app rop riate features in the language y
  • u
cho
  • se.
Lisp is not the right language fo r every p roblem. \Y
  • u
got to dance with the
  • ne
that b rung y
  • u."
{ Bea r Bry ant Lisp is go
  • d
fo r:
  • Explo
rato ry p rogramm ing
  • Rapid
p rotot yping
  • Minimizi
ng time-to-ma rk et
  • Single-p
rogram m er (o r single-digit team) p rojects
  • Source-to-source
  • r
data-to-data transfo rmation Compilers and
  • ther
translato rs Problem-sp ecic languages
  • Dynamic
dispatch and creation (compiler available at run-time)
  • Tight
integration
  • f
mo dules in
  • ne
image (as
  • pp
  • sed
to Unix's cha racter pip e mo del)
  • High
degree
  • f
interaction (read-eval-p rint, CLIM)
  • User-extensible
applications (gnu emacs) \I b elieve go
  • d
soft w a re is written b y small teams
  • f
t w
  • ,
three,
  • r
four p eople interacting with each
  • ther
at a very high, dense level." { John W a rno ck 20
slide-21
SLIDE 21 1.2. Ho w do I kno w if it's go
  • d?
Cho
  • se
the Right Language \Once y
  • u
a re an exp erienced Lisp p rogrammer, it's ha rd to return to any
  • ther
language." { Rob ert R. Kessler Current Lisp implem entations a re not so go
  • d
fo r:
  • P
ersistent sto rage (data base)
  • Maximizing
resource use
  • n
small machines
  • Projects
with hundreds
  • f
p rogrammers
  • Close
communication with fo reign co de
  • Delivering
small-i m age applications
  • Real-time
control (but Gensym did it)
  • Projects
with inexp erienced Lisp p rogrammer s
  • Some
kinds
  • f
numerical
  • r
cha racter computation (W
  • rks
ne with ca reful decla rations, but the Lisp eciency mo del is ha rd to lea rn.) 21
slide-22
SLIDE 22 2. Tips
  • n
Built-in F unctionalit y Built-in F unctionalit y \No doubt ab
  • ut
it, Common Lisp is a big language" { Guy Steele
  • 622
built-in functions (in
  • ne
p re-ANSI CL)
  • 86
macros
  • 27
sp ecial fo rms
  • 54
va riables
  • 62
constants But what counts as the language itself ?
  • C++
has 48 reserved w
  • rds
  • ANSI
CL is do wn to 25 sp ecial fo rms
  • The
rest can b e thought
  • f
as a required lib ra ry Either w a y , the Lisp p rogrammer needs some help: Which built-in functionalit y to mak e use
  • f
Ho w to use it 22
slide-23
SLIDE 23 2. Tips
  • n
Built-in F unctionalit y DEFV AR and DEFP ARAMETER Use defvar fo r things y
  • u
don't w ant to re-initia li ze up
  • n
re-load. (defvar *options* '()) (defun add-opti
  • n
(x) (pushnew x *options* )) Here y
  • u
might have done (add-optio n ...) many times b efo re y
  • u
re-load the le{p erhaps some even from another le. Y
  • u
usually don't w ant to thro w a w a y all that data just b ecause y
  • u
re-load this deni- tion. On the
  • ther
hand, some kinds
  • f
  • ptions
do w ant to get re-initial i zed up
  • n
re-load... (defpara me ter *use-expe ri men ta l- mod e* nil "Set this to T when experime nt al code works.") Later y
  • u
might edit this le and set the va riable to T, and then re-load it, w anting to see the eect
  • f
y
  • ur
edits. Recommendation: Igno re the pa rt in CLtL that sa ys defvar is fo r va riables and defparam et er is fo r pa rame- ters. The
  • nly
useful dierence b et w een these is that defvar do es its assignment
  • nly
if the va riable is un- b
  • und,
while defparam ete r do es its assignment uncon- ditionall y . 23
slide-24
SLIDE 24 2. Tips
  • n
Built-in F unctionalit y EV AL-WHEN (eval-wh en (:execute ) ...) = (eval-whe n (:compile- top le vel ) ...) + (eval-whe n (:load-top le vel ) ...) Also, tak e ca re ab
  • ut
explicitly nesting eval-when fo rms. The eect is not generally intuitive fo r most p eople. 24
slide-25
SLIDE 25 2. Tips
  • n
Built-in F unctionalit y FLET to Avoid Co de Duplication Consider the follo wing example's duplicated use
  • f
(f (g (h))). (do ((x (f (g (h))) (f (g (h))))) (nil) ...) Every time y
  • u
edit
  • ne
  • f
the (f (g (h)))'s, y
  • u
p rob- ab y w ant to edit the
  • ther,
to
  • .
Here is a b etter mo d- ula rit y: (flet ((fgh () (f (g (h))))) (do ((x (fgh) (fgh))) (nil) ...)) (This might b e used as an a rgument against do.) Simil a rl y , y
  • u
might use lo cal functions to avoid dupli- cation in co de b ranches that dier
  • nly
in their dynamic state. F
  • r
example, (defmacr
  • handler-ca
se- if (test form &rest cases) (let ((do-it (gensym "DO-IT")) ) `(flet ((,do-it () ,form)) (if test (handler- cas e (,do-it) ,@cases) (,do-it)) ))) 25
slide-26
SLIDE 26 2. Tips
  • n
Built-in F unctionalit y DEFP A CKA GE Programmi ng in the la rge is supp
  • rted
b y a design st yle that sepa rates co de into mo dules with clea rly dened interfaces. The Common Lisp pack age system serves to avoid name clashes b et w een mo dules, and to dene the in- terface to each mo dule.
  • There
is no top level (b e thread-safe)
  • There
a re
  • ther
p rograms (use pack ages)
  • Mak
e it easy fo r y
  • ur
consumers Exp
  • rt
  • nly
what the consumer needs
  • Mak
e it easy fo r maintai ners License to change non-exp
  • rted
pa rt (defpack ag e "PARSER" (:use "LISP" #+Lucid "LCL" #+Allegr
  • "EXCL")
(:export "PARSE" "PARSE-FI LE " "START-PAR SER
  • W
IN DOW " "DEFINE-G RAM MA R" "DEFINE-T OKE NI ZER ") ) Some put exp
  • rted
symb
  • ls
at the top
  • f
the le where they a re dened. W e feel it is b etter to put them in the defpackage , and use the edito r to nd the co rresp
  • nding
denitions. 26
slide-27
SLIDE 27 2. Tips
  • n
Built-in F unctionalit y Understanding Conditions vs Erro rs Lisp assures that most erro rs in co de will not co rrupt data b y p roviding an active condition system. Lea rn the dierence b et w een erro rs and conditions. All erro rs a re conditions; not all conditions a re erro rs. Distinguish three concepts:
  • Signaling
a condition| Detecting that something unusual has happ ened.
  • Providing
a resta rt| Establishing
  • ne
  • f
p
  • ssibly
several
  • ptions
fo r continuing.
  • Handling
a condition| Selecting ho w to p ro ceed from availabl e
  • ptions.
27
slide-28
SLIDE 28 2. Tips
  • n
Built-in F unctionalit y Erro r Detection Pick a level
  • f
erro r detection and handling that matches y
  • ur
intent. Usually y
  • u
don't w ant to let bad data go b y , but in many cases y
  • u
also don't w ant to b e in the debugger fo r inconsequential reasons. Strik e a balance b et w een tolerance and pickiness that is app rop riate to y
  • ur
application. Bad: what if its not an integer? (defun parse-da te (string) "Read a date from a string. ..." (multipl e-v al ue- bi nd (day-of-m
  • nt
h string-pos it ion ) (parse-in teg er string :junk-all
  • we
d t) ...)) Questionable: what if memo ry runs
  • ut?
(ignore- er ror s (parse-dat e string)) Better: catches exp ected erro rs
  • nly
(handler- cas e (parse-dat e string) (parse-err
  • r
nil)) 28
slide-29
SLIDE 29 2. Tips
  • n
Built-in F unctionalit y W riting Go
  • d
Erro r Messages
  • Use
full sentences in erro r messages (upp ercase initial, trailing p erio d).
  • No
"Error: "
  • r
";;" p rex. The system will sup- ply such a p rex if needed.
  • Do
not b egin an erro r message with a request fo r a fresh line. The system will do this automaticall y if necessa ry .
  • As
with
  • ther
fo rmat strings, don't use emb edded tab cha racters.
  • Don't
mention the consequences in the erro r mes- sage. Just describ e the situation itself.
  • Don't
p resupp
  • se
the debugger's user interface in describing ho w to continue. This ma y cause p
  • rta-
bilit y p roblems since dierent implementati
  • ns
use dierent interfaces. Just describ e the abstract ef- fect
  • f
a given action.
  • Sp
ecify enough detail in the message to distinguish it from
  • ther
erro rs, and if y
  • u
can, enough to help y
  • u
debug the p roblem later if it happ ens. 29
slide-30
SLIDE 30 2. Tips
  • n
Built-in F unctionalit y W riting Go
  • d
Erro r Messages (cont'd) Bad: (error "~%>> Error: Foo. Type :C to continue. ") Better: (cerror "Specify a replaceme nt sentence interacti vel y. " "An ill-form ed sentence was encounter ed :~ % ~A" sentence) 30
slide-31
SLIDE 31 2. Tips
  • n
Built-in F unctionalit y Using the Condition System Sta rt with these:
  • erro
r, cerro r
  • w
a rn
  • handler-case
  • with-simple-resta
rt
  • unwind-p
rotect Go
  • d:
standa rd use
  • f
w a rn (defvar *word* '?? "The word we are currently working
  • n.")
(defun lex-warn (format-s tr &rest args) "Lexical warning; like warn, but first tells what word caused the warning." (warn "For word ~a: ~?" *word* format-st r args)) 31
slide-32
SLIDE 32 2. Tips
  • n
Built-in F unctionalit y HANDLER-CASE, WITH-SIMPLE-REST ART Go
  • d:
handle sp ecic erro rs (defun eval-exp (exp) "If possible evaluate this exp;
  • therwis
e return it." ;; Guard against errors in evaluati ng exp (handler
  • ca
se (if (and (fboundp (op exp)) (every #'is-const an t (args exp))) (eval exp) exp) (arithmet ic
  • er
ro r () exp))) Go
  • d:
p rovide resta rts (defun top-leve l (&key (prompt "=> ") (read #'read) (eval #'eval) (print #'print) ) "A read-eva l- pri nt loop." (with-si mpl e- res ta rt (abort "Exit
  • ut
  • f
the top level.") (loop (with-si mp le- re sta rt (abort "Return to top level loop.") (format t "~&~a" prompt) (funcall print (funcall eval (funcall read))))) )) 32
slide-33
SLIDE 33 2. Tips
  • n
Built-in F unctionalit y UNWIND-PROTECT unwind-p ro tec t implem ents imp
  • rtant
functionalit y that every
  • ne
should kno w ho w to use. It is not just fo r sys- tem p rogramm ers. W atch
  • ut
fo r multi-taski ng, though. F
  • r
example, im- plementing some kinds
  • f
state-binding with unwind-pr
  • t
ect might w
  • rk
w ell in a single-threaded environment, but in an environment with multi-task i ng, y
  • u
  • ften
have to b e a little mo re ca reful. (unwind- pr
  • te
ct (progn fo rm 1 fo rm 2 ... fo rm n ) cleanup 1 cleanup 2 ... cleanup n )
  • Never
assume form 1 will get run at all.
  • Never
assume form n w
  • n't
run to completion. 33
slide-34
SLIDE 34 2. Tips
  • n
Built-in F unctionalit y UNWIND-PROTECT (cont'd) Often y
  • u
need to save state b efo re entering the unwind-p ro tec t, and test b efo re y
  • u
resto re state: P
  • ssibly
Bad: (with multi-taski ng) (catch 'robot-o p (unwind- pro te ct (progn (turn-on- mot
  • r
) (manipula te) ) (turn-off
  • m
  • to
r) )) Go
  • d:
(safer) (catch 'robot-o p (let ((status (motor-st atu s motor))) (unwind-p ro tec t (progn (turn-on- mot
  • r
motor) (manipula te motor)) (when (motor-o n? motor) (turn-off- mo tor motor)) (setf (motor-s tat us motor) status))) ) 34
slide-35
SLIDE 35 2. Tips
  • n
Built-in F unctionalit y I/O Issues: Using F ORMA T
  • Don't
use T ab cha racters in fo rmat strings (o r any strings intended fo r
  • utput).
Dep ending
  • n
what column y
  • ur
  • utput
sta rts in, the tab stops ma y not line up the same
  • n
  • utput
as they did in the co de!
  • Don't
use "#<~S ~A>" to p rint unreadable
  • bjects.
Use print-unr ea dab le
  • ob
je ct instead.
  • Consider
putting fo rmat directives in upp ercase to mak e them stand
  • ut
from lo w ercase text sur- rounding. F
  • r
example, "Foo: ~A" instead
  • f
"Foo: ~a".
  • Lea
rn useful idioms. F
  • r
example: ~{~A~^, ~} and ~:p.
  • Be
conscious
  • f
when to use ~& versus ~%. Also, "~2%" and "~2&" a re also handy . Most co de which
  • utputs
a single line should sta rt with ~& and end with ~%. (format t "~&This is a test.~%") This is a test.
  • Be
a w a re
  • f
implementati
  • n
extensions. They ma y not b e p
  • rtable,
but fo r non-p
  • rtable
co de might b e very useful. F
  • r
example, Genera's ! and fo r handling indentation. 35
slide-36
SLIDE 36 2. Tips
  • n
Built-in F unctionalit y Using Streams Co rrectly
  • *standard-
  • u
tpu t* and *standard- in put * vs *terminal- io * Do not assume *standard
  • in
pu t* and *standar d-
  • ut
pu t* will b e b
  • und
to *terminal
  • io
* (o r, in fact, to any interactive stream). Y
  • u
can bind them to such a stream, ho w ever. T ry not to use *terminal
  • i
  • *
directly fo r input
  • r
  • utput.
It is p rima ri l y availabl e as a stream to which
  • ther
streams ma y b e b
  • und,
  • r
ma y indi- rect (e.g., b y synonym streams).
  • *error-out
pu t* vs *debug-io* Use *error-ou tp ut * fo r w a rnings and erro r mes- sages that a re not accompanied b y any user inter- action. Use *debug-io * fo r interactive w a rnings, erro r mes- sages, and
  • ther
interactions not related to the no rmal function
  • f
a p rogram. In pa rticula r, do not rst p rint a message
  • n
*error-ou tpu t* and then do a debugging session
  • n
*debug-io* , ex- p ecting those to b e the same stream. Instead, do each interaction consistently
  • n
  • ne
stream. 36
slide-37
SLIDE 37 2. Tips
  • n
Built-in F unctionalit y Using Streams Co rrectly (cont'd)
  • *trace-out
pu t* This can b e used fo r mo re than just receiving the
  • utput
  • f
trace. If y
  • u
write debugging routines that conditionally p rint helpful info rmation with-
  • ut
stopping y
  • ur
running p rogram, consider do- ing
  • utput
to this stream so that if *trace-ou tp ut * is redirected, y
  • ur
debugging
  • utput
will to
  • .
A useful test: If someone re-b
  • und
  • nly
  • ne
  • f
several I/O streams y
  • u
a re using, w
  • uld
it mak e y
  • ur
  • utput
lo
  • k
stupid? 37
slide-38
SLIDE 38 3. Tips
  • n
Nea r-Standa rd T
  • ls
Using Nea r-Standa rd T
  • ls
Some functionalit y is not built in to the language, but is used b y most p rogrammers. This divides into exten- sions to the language and to
  • ls
that help y
  • u
develop p rograms. Extensions
  • defsystem
to dene a p rogram
  • CLIM,
CLX, etc. graphics lib ra ri es T
  • ls
  • emacs
from FSF, Lucid indentation, font/colo r supp
  • rt
denition/a rglist/do c/regexp nding communication with lisp
  • xref,
manual, etc. from CMU
  • Bro
wsers, debuggers, p rolers from vendo rs 38
slide-39
SLIDE 39 3. Tips
  • n
Nea r-Standa rd T
  • ls
DEFSYSTEM Pick a public domain version
  • f
defsyste m (unfo rtu- nately , dpANS CL has no standa rd).
  • Put
absolute pathnames in
  • ne
place
  • nly
  • Load
everything through the defsystem
  • Distinguish
compiling from loading
  • Optionally
do version control (defpack ag e "PARSER" ...) (defsyst em parser (:source "/lab/ind exi ng /pa rs er /*" ) (:parts utilities "macros" "grammar " "tokeniz er " "optimizer " "debugge r" "toplevel " #+CLIM "clim-gr aph ic s" #+CLX "clx-gra ph ics ") )
  • Mak
e sure y
  • ur
system loads with no compiler w a rnings (rst time and subsequent times) (lea rn to use (declare (ignore ...)))
  • Mak
e sure the system can b e compiled from scratch (eliminate lingering b
  • tstrapping
p roblems) 39
slide-40
SLIDE 40 3. Tips
  • n
Nea r-Standa rd T
  • ls
Edito r Commands Y
  • ur
edito r should b e able to do the follo wing:
  • Move
ab
  • ut
b y s-exp ressions and sho w matching pa rens
  • Indent
co de p rop erly
  • Find
unbalanced pa rens
  • Ado
rn co de with fonts and colo rs
  • Find
the denition
  • f
any symb
  • l
  • Find
a rguments
  • r
do cumentation fo r any symb
  • l
  • Macro
expand any exp ression
  • Send
the current exp ression, region
  • r
le to Lisp to b e evaluated
  • r
compiled
  • Keep
a histo ry
  • f
commands sent to Lisp and allo w y
  • u
to edit and resend them
  • W
  • rk
with k eyb
  • a
rd, mouse, and menus Emacs can do all these things. If y
  • ur
edito r can't, complain until it is xed,
  • r
get a new
  • ne.
40
slide-41
SLIDE 41 3. Tips
  • n
Nea r-Standa rd T
  • ls
Emacs: Indentation and Comments Don't try to indent y
  • urself.
Instead, let the edito r do it. A nea r-standa rd fo rm has evolved.
  • 80-column
maximum width
  • Ob
ey comment conventions ; fo r inline comment ;; fo r in-function comment ;;; fo r b et w een-function comment ;;;; fo r section header (fo r
  • utline
mo de)
  • cl-indent
lib ra ry can b e told ho w to indent (put 'defvar 'common-l is p-i nd ent
  • f
unc ti
  • n
'(4 2 2))
  • lemacs
can p rovide fonts, colo r (hilit::mo de s-l is t-u pd at e "Lisp" '((";;.*" nil hilit2) ...)) 41
slide-42
SLIDE 42 4. Abstraction Abstraction All p rogramm ing languages allo w the p rogrammer to dene abstractions. All mo dern languages p rovide sup- p
  • rt
fo r:
  • Data
Abstraction (abstract data t yp es)
  • F
unctional Abstraction (functions, p ro cedures) Lisp and
  • ther
languages with closures (e.g., ML, Sather) supp
  • rt:
  • Control
Abstraction (dening iterato rs and
  • ther
new
  • w
  • f
control constructs) Lisp is unique in the degree to which it supp
  • rts:
  • Syntactic
Abstraction (macros, whole new lan- guages) 42
slide-43
SLIDE 43 4. Abstraction Design: Where St yle Begins \The most imp
  • rtant
pa rt
  • f
writing a p rogram is de- signing the data structures. The second most imp
  • r-
tant pa rt is b reaking the va rious co de pieces do wn." { Bill Gates \Exp ert engineers stratify complex designs. : : : The pa rts constructed at each level a re used as p rimi tives at the next level. Each level
  • f
a stratied design can b e thought
  • f
as a sp ecialized language with a va riet y
  • f
p rimi tives and means
  • f
combination app rop riate to that level
  • f
detail." { Ha rold Ab elson and Gerald Sussman \Decomp
  • se
decisions as much as p
  • ssible.
Untangle asp ects which a re
  • nly
seemingly indep endent. Defer those decisions which concern details
  • f
rep resentation as long as p
  • ssible."
{ Niklaus Wirth Lisp supp
  • rts
all these app roaches:
  • Data
Abstraction: classes, structures, deft yp e
  • F
unctional Abstraction: functions, metho ds
  • Interface
Abstraction: pack ages, closures
  • Object-Oriented:
CLOS, closures
  • Stratied
Design: closures, all
  • f
ab
  • ve
  • Dela
y ed Decisions: run-time dispatch 43
slide-44
SLIDE 44 4. Abstraction Design: Decomp
  • sition
\A Lisp p ro cedure is lik e a pa ragraph." { Deb
  • rah
T ata r \Y
  • u
should b e able to explain any mo dule in
  • ne
sen- tence." { W a yne Ratli
  • Strive
fo r simple designs
  • Break
the p roblem into pa rts Design useful subpa rts (stratied) Be
  • pp
  • rtunistic;
use existing to
  • ls
  • Determine
dep endencies Re-mo dula rize to reduce dep endencies Design most dep endent pa rts rst W e will cover the follo wing kinds
  • f
abstraction:
  • Data
abstraction
  • F
unctional abstraction
  • Control
abstraction
  • Syntactic
abstraction 44
slide-45
SLIDE 45 4.1. Data Abstraction Data Abstraction W rite co de in terms
  • f
the p roblem's data t yp es, not the t yp es that happ en to b e in the implementati
  • n.
  • Use
defstruct
  • r
defclass fo r reco rd t yp es
  • Use
inline functions as aliases (not macros)
  • Use
deftype
  • Use
decla rations and :type slots fo r eciency and/o r do cumentation
  • V
a riable names give info rmal t yp e info rmation Prett y Go
  • d:
sp ecies some t yp e info (defclas s event () ((starti ng- ti me :type integer) (location :type location) (duration :type integer :initfor m 0))) Better: p roblem-sp ecic t yp e info (deftype time () "Time in seconds" 'integer) (defcons ta nt +the-dawn-
  • f
  • ti
me + "Midnigh t, January 1, 1900" (defclas s event () ((starti ng- ti me :type time :initfor m +the-daw n-
  • f-
ti me+ ) (location :type location) (duration :type time :initfor m 0))) 45
slide-46
SLIDE 46 4.1. Data Abstraction Use Abstract Data T yp es Intro duce abstract data t yp es with accesso rs: Bad:
  • bscure
accesso r, eval (if (eval (cadar rules)) ...) Better: intro duce names fo r accesso rs (declaim (inline rule-ant ece de nt )) (defun rule-ant ece de nt (rule) (second rule)) (if (holds? (rule-an tec ed ent (first rules))) ...) Usually Best: intro duce rst-class data t yp e (defstru ct rule name antecede nt consequent )
  • r
(defstru ct (rule (:type list)) name antecede nt consequent )
  • r
(defclas s rule () (name antecedent consequen t) ) 46
slide-47
SLIDE 47 4.1. Data Abstraction Impleme nt Abstract Data T yp es Kno w ho w to map from common abstract data t yp es to Lisp implementati
  • ns.
  • Set:
list, bit-vecto r, integer, any table t yp e
  • Sequence:
list, vecto r, dela y ed-evaluation stream
  • Stack:
list, vecto r (with ll-p
  • inter)
  • Queue:
tconc, vecto r (with ll-p
  • inter)
  • T
able: hash table, alist, plist, vecto r
  • T
ree, Graph: cons, structures, vecto r, adjacency matrix Use implem entati
  • ns
that a re already supp
  • rted
(e.g. union, intersec tio n, length fo r sets as lists; logior, logand, logcount fo r sets as integers. Don't b e afraid to build a new implem entati
  • n
if p ro- ling reveals a b
  • ttleneck.
(If Common Lisp's hash tables a re to
  • inecient
fo r y
  • ur
application, consider building a sp ecialized hash table in Lisp b efo re y
  • u
build a sp ecialized hash table in C.) 47
slide-48
SLIDE 48 4.1. Data Abstraction Inherit from Data T yp es Reuse b y inheritance as w ell as direct use
  • structures
supp
  • rt
single inheritance
  • classes
supp
  • rt
multiple inheritance
  • b
  • th
allo w some
  • ver-riding
  • classes
supp
  • rt
mixins Consider a class
  • r
structure fo r the whole p rogram
  • Elimi
nates clutter
  • f
global va riables
  • Thread-safe
  • Can
b e inherited and mo died 48
slide-49
SLIDE 49 4.2. F unctional Abstraction F unctional Abstraction Every function should have:
  • A
single sp ecic purp
  • se
  • If
p
  • ssible,
a generally useful purp
  • se
  • A
meaningful name (names lik e recurse-a ux indicate p roblems)
  • A
structure that is simple to understand
  • An
interface that is simple y et general enough
  • As
few dep endencies as p
  • ssible
  • A
do cumentation string 49
slide-50
SLIDE 50 4.2. F unctional Abstraction Decomp
  • sition
Decomp
  • se
an algo rithm into functions that a re simple, meaningful and useful. Example from comp.lang.li sp discussion
  • f
loop vs. map: (defun least-co mmo n- sup er cla ss (instance s) (let ((candid ate s (reduce #'inters ect io n (mapcar #'(lambda (instance) (clos:cl ass
  • p
rec ed en ce- li st (class-of instance) )) instances) )) (best-cand id ate (find-cl ass t))) (mapl #'(lambd a (candidate s) (let ((current
  • c
and id at e (first candidat es) ) (remaining
  • ca
nd id ate s (rest candidate s) )) (when (and (subtype p current-ca ndi da te best-candi dat e) (every #'(lambda (remainin g-c an di dat e) (subtype p current-ca nd ida te remaining- ca ndi da te) ) remaining
  • ca
nd ida te s)) (setf best-cand id at e current- can di da te) )) ) candidat es ) best-cand id ate )) 50
slide-51
SLIDE 51 4.2. F unctional Abstraction Decomp
  • sition
V ery Go
  • d:
Chris Riesb eck (defun least-co mmo n- sup er cla ss (instance s) (reduce #'more-spe cif ic
  • cl
as s (common-su per cl ass es instances ) :initial-v alu e (find-clas s 't))) (defun common-s upe rc las se s (instanc es ) (reduce #'intersec tio n (superclas s-l is ts instances ))) (defun supercla ss- li sts (instanc es) (loop for instance in instance s collect (clos:cla ss- pr ec ede nc e-l is t (class-o f instance )) )) (defun more-spe cif ic
  • cl
as s (class1 class2) (if (subtypep class2 class1) class2 class1))
  • Each
function is very understandable
  • Control
structure is clea r: Tw
  • reduces,
an intersection and a lo
  • p/collect
  • But
reusablit y is fairly lo w 51
slide-52
SLIDE 52 4.2. F unctional Abstraction Decomp
  • sition
Equally Go
  • d:
and mo re reusable (defun least-co mmo n- sup er cla ss (instance s) "Find a least class that all instances belong to." (least-u ppe r- bou nd (mapcar #'class-
  • f
instances ) #'clos:cl as s-p re ced en ce- li st #'subtype p) ) (defun least-up per
  • b
  • un
d (elements supers sub?) "Element
  • f
lattice that is a super
  • f
all elements. " (reduce #'(lambda (x y) (binary-l ea st- up pe r-b
  • u
nd x y supers sub?)) elements)) (defun binary-l eas t- upp er
  • bo
un d (x y supers sub?) "Least upper bound
  • f
two elements. " (reduce- if sub? (intersect io n (funcall supers x) (funcall supers y)))) (defun reduce-i f (pred sequence) "E.g. (reduce-if #'> numbers) computes maximum" (reduce #'(lambda (x y) (if (funcall pred x y) x y)) sequence))
  • Individual
functions remain understandable
  • Still
2 reduces, an intersection and a map ca r
  • Stratied
design yields mo re useful functions 52
slide-53
SLIDE 53 4.2. F unctional Abstraction Rule
  • f
English T ranslation T
  • insure
that y
  • u
sa y what y
  • u
mean: 1. Sta rt with an English description
  • f
algo rithm 2. W rite the co de from the description 3. T ranslate the co de back into English 4. Compa re 3 to 1 Example: 1. \Given a list
  • f
monsters, determine the numb er that a re sw a rms." 2. (defun count-swar m (monster
  • l
ist ) (apply '+ (mapcar #'(lambda (monster) (if (equal (object-t ype (get-obj ect monster) ) 'swarm) 1 0)) monster-li st )) ) 3. \T ak e the list
  • f
monsters and p ro duce a 1 fo r a monster whose t yp e is sw a rm, and a fo r the
  • thers.
Then add up the list
  • f
numb ers." 53
slide-54
SLIDE 54 4.2. F unctional Abstraction Rule
  • f
English T ranslation Better: 1. \Given a list
  • f
monsters, determine the numb er that a re sw a rms." 2. (defun count-swar ms (monster- nam es ) "Count the swarms in a list
  • f
monster names." (count-if #'swarm-p monster-na me s :key #'get-ob je ct) )
  • r
(count 'swarm monster- na mes :key #'get-obj ec t- typ e)
  • r
(loop for name in monster-n am es count (swarm-p (get-obj ect monster)) ) 3. \Given a list
  • f
monster names, count the numb er that a re sw a rms." 54
slide-55
SLIDE 55 4.2. F unctional Abstraction Use Lib ra ry F unctions Lib ra ri es ma y have access to lo w-level eciency hacks, and a re
  • ften
ne-tuned. BUT they ma y b e to
  • general,
hence inecient. W rite a sp ecic version when eciency is a p roblem. Go
  • d:
sp ecic, concise (defun find-cha rac te r (char string) "See if the character appears in the string." (find char string)) Go
  • d:
ecient (defun find-cha rac te r (char string) "See if the character appears in the string." (declare (characte r char) (simple-s tri ng string)) (loop for ch across string when (eql ch char) return ch)) 55
slide-56
SLIDE 56 4.2. F unctional Abstraction Use Lib ra ry F unctions Given build1, which maps n to a list
  • f
n x's: (build1 4) ) (x x x x) T ask: Dene build-it so that: (build-i t '(4 3)) ) ((x x x x) () (x x x)) Incredibly Bad: (defun round3 (x) (let ((result '())) (dotimes (n (length x) result) (setq result (cons (car (nthcdr n x)) result)) )) ) (defun build-it (arg-list ) (let ((result '())) (dolist (a (round3 arg-list) result) (setq result (cons (build1 a) result))) )) Problems:
  • round3
is just another name fo r reverse
  • (car
(nthcdr n x)) is (nth n x)
  • dolist
w
  • uld
b e b etter than dotimes here
  • push
w
  • uld
b e app rop riate here
  • (mapcar
#'build1 numbers) do es it all 56
slide-57
SLIDE 57 4.3. Control Abstraction Control Abstraction Most algo rithm s can b e cha racterized as:
  • Sea
rching (some find find-if mismatch )
  • So
rting (sort merge remove-dup lic at es)
  • Filtering
(remove remove-if mapcan)
  • Mapping
(map mapcar mapc)
  • Combining
(reduce mapcan)
  • Counting
(count count-if) These functions abstract common control patterns. Co de that uses them is:
  • Concise
  • Self-do
cumenting
  • Easy
to understand
  • Often
reusable
  • Usually
ecient (Better than a non-tail recursion) Intro ducing y
  • ur
  • wn
control abstraction is an imp
  • r-
tant pa rt
  • f
stratied design. 57
slide-58
SLIDE 58 4.3. Control Abstraction Recursion vs. Iteration Recursion is go
  • d
fo r recursive data structures. Many p eople p refer to view a list as a sequence and use iter- ation
  • ver
it, thus de-emphasizing the implementati
  • n
detail that the list is split into a rst and rest. As an exp ressive st yle, tail recursion is
  • ften
considered elegant. Ho w ever, Common Lisp do es not gua rantee tail recursion elimi nati
  • n
so it should not b e used as a substitute fo r iteration in completely p
  • rtable
co de. (In Scheme it is ne.) The Common Lisp do macro can b e thought
  • f
as syn- tactic suga r fo r tail recursion, where the initial values fo r va riables a re the a rgument values
  • n
the rst func- tion call, and the step values a re a rgument values fo r subsequent function calls. do p rovides a lo w level
  • f
abstraction, but versatile and has a simple, explicit execution mo del. 58
slide-59
SLIDE 59 4.3. Control Abstraction Recursion vs. Iteration (cont'd) Bad: (in Common Lisp) (defun any (lst) (cond ((null lst) nil) ((car lst) t) (t (any (cdr lst))))) Better: conventional, concise (defun any (list) "Return true if any member
  • f
list is true." (some #'not-null list))
  • r
(find-if
  • no
t #'null lst)
  • r
(loop for x in list thereis x)
  • r
(explicit) (do ((list list (rest list))) ((null list) nil) (when (first list)) (return t)))) Best: ecient, most concise in this case Don't call any at all! Use (some p list) instead
  • f
(any (mapcar p list)) 59
slide-60
SLIDE 60 4.3. Control Abstraction LOOP \Keep a loop to
  • ne
topic|lik e a letter to y
  • ur
Senato r." { Judy Anderson The Common Lisp loop macro gives y
  • u
the p
  • w
er to exp ress idiomati c usages concisely . Ho w ever it b ea rs the burden that its syntax and semantics a re
  • ften
sub- stantially mo re complex than its alternatives. Whether
  • r
not to use the loop macro is an issue sur- rounded in controversy , and b
  • rders
  • n
a religious w a r. A t the ro
  • t
  • f
the conict is the follo wing somewhat pa rado xical
  • bservation:
  • loop
app eals to naive p rogrammers b ecause it lo
  • ks
lik e English and seems to call fo r less kno wledge
  • f
p rogrammi ng than its alternatives.
  • loop
is not English; its syntax and semantics have subtle intricacies that have b een the source
  • f
many p rogrammi ng bugs. It is
  • ften
b est used b y p eople who've tak en the time to study and un- derstand it|usually not naive p rogrammers. Use the unique features
  • f
lo
  • p
(e.g., pa rallel iteration
  • f
dierent kinds). 60
slide-61
SLIDE 61 4.3. Control Abstraction Simple Iteration Bad: verb
  • se,
control structure unclea r (LOOP (SETQ *WORD* (POP *SENTENCE* )) ;get the next word (COND ;; if no more words then return instantiat ed CD form ;; which is stored in the variable *CONCEPT* ((NULL *WORD*) (RETURN (REMOVE- VAR IA BLE S (VAR-VALUE '*CONCEP T*) )) ) (T (FORMAT T "~%~%Proc ess in g ~A" *WORD*) (LOAD-DEF ) ; look up requests under ; this word (RUN-STAC K)) )) ) ; fire requests
  • No
need fo r global va riables
  • End
test is misleadi ng
  • Not
immedia tely clea r what is done to each w
  • rd
Go
  • d:
conventional, concise, explicit (mapc #'process- wo rd sentence) (remove- var ia ble s (var-value '*concept *) ) (defun process- wor d (word) (format t "~2%Proc ess in g ~A" word) (load-de f word) (run-sta ck) ) 61
slide-62
SLIDE 62 4.3. Control Abstraction Mapping Bad: verb
  • se
; (extract
  • id
  • l
ist 'l_user-r ec s)
  • [lambda]
; WHERE: l_user-re cs is a list
  • f
user records ; RETURNS: a list
  • f
all user id's in l_user-re cs ; USES: extract-i d ; USED BY: process-u ser s, sort-user s (defun extract- id- li st (user-rec s) (prog (id-list) loop (cond ((null user-recs) ;; id-list was construc te d in reverse
  • rder
;; using cons, so it must be reversed now: (return (nreverse id-list))) ) (setq id-list (cons (extract-i d (car user-recs) ) id-list)) (setq user-recs (cdr user-recs )) ;next user record (go loop))) Go
  • d:
conventional, concise (defun extract- id- li st (user-rec
  • rd
  • l
ist ) "Return the user ID's for a list
  • f
users." (mapcar #'extract- id user-reco rd- li st) ) 62
slide-63
SLIDE 63 4.3. Control Abstraction Counting Bad: verb
  • se
(defun size () (prog (size idx) (setq size idx 0) loop (cond ((< idx table-siz e) (setq size (+ size (length (aref table idx))) idx (1+ idx)) (go loop))) (return size))) Go
  • d:
conventional, concise (defun table-co unt (table) ; Formerly called SIZE "Count the number
  • f
keys in a hash-like table." (reduce #'+ table :key #'length)) Also, it couldn't hurt to add: (deftype table () "A table is a vector
  • f
buckets, where each bucket holds an alist
  • f
(key . values) pairs." '(vector cons)) 63
slide-64
SLIDE 64 4.3. Control Abstraction Filtering Bad: verb
  • se
(defun remove-b ad- pr ed- vi sit ed (l badpred closed) ;;; Returns a list
  • f
nodes in L that are not bad ;;; and are not in the CLOSED list. (cond ((null l) l) ((or (funcall badpred (car l)) (member (car l) closed)) (remove-b ad
  • pr
ed
  • vi
si te d (cdr l) badpred closed)) (t (cons (car l) (remove- bad
  • p
re d-v is ite d (cdr l) badpred closed)) ))) Go
  • d:
conventional, concise (defun remove-b ad-
  • r
  • cl
  • s
ed- no de s (nodes bad-node ? closed) "Remove nodes that are bad
  • r
are
  • n
closed list" (remove- if #'(lambda (node) (or (funcall bad-node? node) (member node closed)) ) nodes)) 64
slide-65
SLIDE 65 4.3. Control Abstraction Control Flo w: Keep It Simple Non-lo cal control
  • w
is ha rd to understand Bad: verb
  • se,
violates referential transpa rency (defun isa-test (x y n) (catch 'isa (isa-test 1 x y n))) (defun isa-test 1 (x y n) (cond ((eq x y) t) ((member y (get x 'isa)) (throw 'isa t)) ((zerop n) nil) (t (any (mapcar #'(lambd a (xx) (isa-test xx y (1- n)) ) (get x 'isa) ))) ) ) Problems:
  • catch/thro
w is gratuitous
  • member
test ma y
  • r
ma y not b e helping
  • mapcar
generates ga rbage
  • any
tests to
  • late;
throw tries to x this result is that any never gets called! 65
slide-66
SLIDE 66 4.3. Control Abstraction Keep It Simple Some recommendations fo r use
  • f
catch and throw:
  • Use
catch and throw as sub-p rimi ti ves when imple- menting mo re abstract control structures as macros, but do not use them in no rmal co de.
  • Sometimes
when y
  • u
establish a catch, p rograms ma y need to test fo r its p resence. In that case, resta rts ma y b e mo re app rop riate. 66
slide-67
SLIDE 67 4.3. Control Abstraction Keep It Simple Go
  • d:
(defun isa-test (sub super max-dept h) "Test if SUB is linked to SUPER by a chain
  • f
ISA links shorter than max-depth ." (and (>= max-depth 0) (or (eq sub super) (some #'(lambd a (parent) (isa-test parent super (- max-dept h 1))) (get sub 'isa))))) Also go
  • d:
uses to
  • ls
(defun isa-test (sub super max-dept h) (depth-f irs t- sea rc h :start sub :goal (is super) :success
  • r
s #'get-is a :max-dep th max-depth )) \W rite clea rly|don't b e to
  • clever."
{ Kernighan & Plauger Be Aw a re: Do es \imp roving" something change the semantics? Do es that matter? 67
slide-68
SLIDE 68 4.3. Control Abstraction Avoid Complicated Lamb da Exp ressions When a higher-o rder function w
  • uld
need a compli- cated lamb da exp ression, consider alternatives:
  • dolist
  • r
loop
  • generate
an intermediate (ga rbage) sequence
  • Series
  • Macros
  • r
read macros
  • lo
cal function { Sp ecic: mak es it clea r where function is used { Do esn't clutter up global name space { Lo cal va riables needn't b e a rguments { BUT: some debugging to
  • ls
w
  • n't
w
  • rk
68
slide-69
SLIDE 69 4.3. Control Abstraction Avoid Complicated Lamb da Exp ressions Find the sum
  • f
the squa res
  • f
the
  • dd
numb ers in a list
  • f
integers: All Go
  • d:
(reduce #'+ numbers :key #'(lambda (x) (if (oddp x) (* x x) 0))) (flet ((square-
  • dd
(x) (if (oddp x) (* x x) 0))) (reduce #'+ numbers :key #'square
  • dd)
) (loop for x in list when (oddp x) sum (* x x)) (collect
  • s
um (choose-if #'oddp numbers)) Also consider: (ma y b e app rop riate sometimes) ;; Introduce read macro: (reduce #'+ numbers :key #L(if (oddp _) (* _ _) 0)) ;; Generate intermed iat e garbage: (reduce #'+ (remove #'evenp (mapcar #'square numbers)) ) 69
slide-70
SLIDE 70 4.3. Control Abstraction F unctional vs. Imp erative St yle It has b een a rgued that imp erative st yle p rograms a re ha rder to reason ab
  • ut.
Here is a bug that stems from an imp erative app roach: T ask: W rite a version
  • f
the built-in function find. Bad: inco rrect (defun i-find (item seq &key (test #'eql) (test-not nil) (start s-flag) (end nil) (key #'identit y) (from-end nil)) (if s-flag (setq seq (subseq seq start))) (if end (setq seq (subseq seq end))) ...) Problems:
  • T
aking subsequences generates ga rbage
  • No
app reciation
  • f
list/vecto r dierences
  • Erro
r if b
  • th
sta rt and end a re given Erro r stems from the up date to seq 70
slide-71
SLIDE 71 4.3. Control Abstraction Example: Simplication T ask: a simpli er fo r logical exp ressions: (simp '(and (and a b) (and (or c (or d e)) f))) ) (AND A B (OR C D E) F) Not bad, but not p erfect: (defun simp (pred) (cond ((atom pred) pred) ((eq (car pred) 'and) (cons 'and (simp-aux 'and (cdr pred)))) ((eq (car pred) 'or) (cons 'or (simp-aux 'or (cdr pred)))) (t pred))) (defun simp-aux (op preds) (cond ((null preds) nil) ((and (listp (car preds)) (eq (caar preds)
  • p))
(append (simp-au x
  • p
(cdar preds)) (simp-au x
  • p
(cdr preds)))) (t (cons (simp (car preds)) (simp-au x
  • p
(cdr preds))))) ) 71
slide-72
SLIDE 72 4.3. Control Abstraction A Program to Simplify Exp ressions Problems:
  • No
meaningful name fo r simp-aux
  • No
reusable pa rts
  • No
data accesso rs
  • (and),
(and a) not simplied Better: usable to
  • ls
(defun simp-boo l (exp) "Simplif y a boolean (and/or) expressio n. " (cond ((atom exp) exp) ((member (op exp) '(and
  • r))
(maybe-ad d (op exp) (collect-a rg s (op exp) (mapcar #'simp-b
  • ol
(args exp))))) (t exp))) (defun collect- arg s (op args) "Return the list
  • f
args, splicing in args that have the given
  • perator
,
  • p.
Useful for simplify ing exps with associat e
  • perator
s." (loop for arg in args when (starts-wi th arg
  • p)
nconc (collect- ar gs
  • p
(args arg)) else collect arg)) 72
slide-73
SLIDE 73 4.3. Control Abstraction Build Reusable T
  • ls
(defun starts-w ith (list element) "Is this a list that starts with the given element?" (and (consp list) (eql (first list) element))) (defun maybe-ad d (op args &optional (default (get-ident it y
  • p)))
"If 1 arg, return it; if 0, return the default. If there is more than 1 arg, cons
  • p
  • n
them. Example: (maybe-ad d 'progn '((f x))) ==> (f x) Example: (maybe-ad d '* '(3 4)) ==> (* 3 4). Example: (maybe-ad d '+ '()) ==> 0, assuming is defined as the identity for +." (cond ((null args) default) ((length=1 args) (first args)) (t (cons
  • p
args)))) (deftabl e identity :init '((+ 0) (* 1) (and t) (or nil) (progn nil))) 73
slide-74
SLIDE 74 4.4. Syntactic Abstraction A Language fo r Simplifying T ask: A Simpli er fo r all Exp ressions: (simplif y '(* 1 (+ x (- y y)))) ==> x (simplif y '(if (= 1) (f x))) ==> nil (simplif y '(and a (and (and) b))) ==> (and a b) Syntactic abstraction denes a new language that is app rop riate to the p roblem. This is a p roblem-o r iented (as
  • pp
  • sed
to co de-o riented) app roach. Dene a language fo r simpli cation rules, then write some: (define- si mpl if ier exp-simpl if ie r ((+ x 0) ==> x) ((+ x) ==> x) ((- x 0) ==> x) ((- x x) ==> 0) ((if t x y) ==> x) ((if nil x y) ==> y) ((if x y y) ==> y) ((and) ==> t) ((and x) ==> x) ((and x x) ==> x) ((and t x) ==> x) ...) 74
slide-75
SLIDE 75 4.4. Syntactic Abstraction Design Y
  • ur
Language Ca refully \The abilit y to change notations emp
  • w
ers human b eings." { Scott Kim Bad: verb
  • se,
b rittle (setq times0-ru le '( simplify (* (? e1) 0) times0-r ule ) ) (setq rules (list times0-rul e ...))
  • Insucient
abstraction
  • Requires
naming times0-rul e three times
  • Intro
duces unneeded global va riables
  • Unconventional
indentation Sometimes it is useful to name rules: (defrule times0-ru le (* ?x 0) ==> 0) (Although I w
  • uldn't
recommend it in this case.) 75
slide-76
SLIDE 76 4.4. Syntactic Abstraction An Interp reter fo r Simplifying No w write an interp reter (o r a compiler): (defun simplify (exp) "Simplif y expressi
  • n
by first simplifyin g componen ts ." (if (atom exp) exp (simplify
  • ex
p (mapcar #'simplif y exp)))) (defun-m em
  • simplify
  • ex
p (exp) "Simplif y expressi
  • n
using a rule,
  • r
math." ;; The expressio n is non-atomi c. (rule-ba sed
  • t
ran sl ato r exp *simplif ica ti
  • n-
ru le s* :rule-pat te rn #'first :rule-res po nse #'third :action #'simpli fy :otherwis e #'eval-exp )) This solution is go
  • d
b ecause:
  • Simplicati
  • n
rules a re easy to write
  • Control
  • w
is abstracted a w a y (mostly)
  • It
is easy to verify the rules a re co rrect
  • The
p rogram can quickly b e up and running. If the app roach is sucient, w e're done. If the app roach is insucient, w e've saved time. If it is just slo w, w e can imp rove the to
  • ls,
and
  • ther
uses
  • f
the to
  • ls
will b enet to
  • .
76
slide-77
SLIDE 77 4.4. Syntactic Abstraction An Interp reter fo r T ranslating \Success comes from doing the same thing
  • ver
and
  • ver
again; each time y
  • u
lea rn a little bit and y
  • u
do a little b etter the next time." { Jonathan Sachs Abstract
  • ut
the rule-based translato r: (defun rule-bas ed- tr ans la tor (input rules &key (matcher #'pat-mat ch ) (rule-pat ter n #'first) (rule-re spo ns e #'rest) (action #identity ) (sub #'sublis) (otherwis e #'identi ty )) "Find the first rule that matches input, and apply the action to the result
  • f
substitut in g the match result into the rule's response. If no rule matches, apply
  • therwis
e to the input." (loop for rule in rules for result = (funcall matcher (funcall rule-patte rn rule) input) when (not (eq result fail)) do (RETURN (funcall action (funcall sub result (funcall rule-respo nse rule)))) finally (RETURN (funcall
  • therwise
input)))) If this implem entati
  • n
is to
  • slo
w, w e can index b etter
  • r
compile. Sometimes, reuse is at an info rmal level: seeing ho w the general to
  • l
is built allo ws a p rogrammer to con- struct a custom to
  • l
with cut and paste. 77
slide-78
SLIDE 78 4.4. Syntactic Abstraction Saving duplicate w
  • rk:
defun-memo Less extreme than dening a whole new language is to augment the Lisp language with new macros. defun-me mo mak es a function rememb er all computa- tions it has made. It do es this b y maintaini ng a hash table
  • f
input/output pairs. If the rst a rgument is just the function name, 1
  • f
2 things happ en: [1] If there is exactly 1 a rg and it is not a &rest a rg, it mak es a eql table
  • n
that a rg. [2] Otherwise, it mak es an equal table
  • n
the whole a rglist. Y
  • u
can also replace fn-name with (name :test ... :size ... :k ey-exp ...). This mak es a table with given test and size, indexed b y k ey-exp. The hash table can b e clea red with the clea r-mem
  • function.
Examples: (defun-m em
  • f
(x) ;; eql table keyed
  • n
x (complex
  • co
mp uta ti
  • n
x)) (defun-m em
  • (f
:test #'eq) (x) ;; eq table keyed
  • n
x (complex
  • co
mp uta ti
  • n
x)) (defun-m em
  • g
(x y z) ;; equal table (another
  • co
mp uta ti
  • n
x y z)) ;; keyed
  • n
  • n
(x y . z) (defun-m em
  • (h
:key-exp x) (x &optional debug?) ;; eql table keyed
  • n
x ...) 78
slide-79
SLIDE 79 4.4. Syntactic Abstraction Saving Duplicate W
  • rk:
defun-memo (defmacr
  • defun-memo
(fn-name- an d-o pt ion s (&rest args) &body body) ;; Document at ion string
  • n
previous page (let ((vars (arglist- va rs args))) (flet ((gen-body (fn-name &key (test '#'equal ) size key-exp) `(eval-whe n (load eval compile) (setf (get ',fn-name 'memoize- ta bl e) (make-has h-t ab le :test ,test ,@(when size `(:size ,size)))) (defun ,fn-name ,args (gethash
  • or
  • s
et
  • de
fa ult ,key-exp (get ',fn-name 'memoize- tab le ) (progn ,@body)))) )) ;; Body
  • f
the macro: (cond ((consp fn-name-an d-
  • pt
io ns) ;; Use user-suppl ie d keywords , if any (apply #'gen-body fn-name-a nd
  • op
ti
  • n
s)) ((and (= (length vars) 1) (not (member '&rest args))) ;; Use eql table if it seems reasonable (gen-body fn-name-a nd-
  • p
tio ns :test '#'eql :key-exp (first vars))) (t ; Otherwis e use equal table
  • n
all args (gen-body fn-name-a nd-
  • p
tio ns :test '#'equal :key-exp `(list* ,@vars))) ))) ) 79
slide-80
SLIDE 80 4.4. Syntactic Abstraction Mo re Macros (defmacr
  • with-gensy
ms (symbols body) "Replace the given symbols with gensym-e d versions , everywhe re in body. Useful for macros." ;; Does this everywhere , not just for "variable s" (sublis (mapcar #'(lambda (sym) (cons sym (gensym (string sym)))) symbols) body)) (defmacr
  • gethash-or
  • se
t- def au lt (key table default) "Get the value from table,
  • r
set it to the default. Doesn't evaluate the default unless needed." (with-ge nsy ms (keyvar tabvar val found-p) `(let ((keyvar ,key) (tabvar ,table)) (multiple
  • va
lu e-b in d (val found-p) (gethash keyvar tabvar) (if found-p val (setf (gethash keyvar tabvar) ,default)) )) )) 80
slide-81
SLIDE 81 4.4. Syntactic Abstraction Use Macros App rop riately (See tuto rial b y Allan W echsler) The design
  • f
macros:
  • Decide
if a macro is really necessa ry
  • Pick
a clea r, consistent syntax fo r the macro
  • Figure
  • ut
the right expansion
  • Use
defmacro and ` to implem ent the mapping
  • In
most cases, also p rovide a functional interface (useful, sometimes easier to alter and continue) Things to think ab
  • ut:
  • Don't
use a macro where a function w
  • uld
suce
  • Mak
e sure nothing is done at expansion time (mostly)
  • Evaluate
a rgs left-to-right,
  • nce
each (if at all)
  • Don't
clash with user names (with-gensyms) 81
slide-82
SLIDE 82 4.4. Syntactic Abstraction Problems with Macros Bad: should b e an inline function (defmacr
  • name-part-
  • f
(rule) `(car ,rule)) Bad: should b e a function (defmacr
  • defpredfun
(name evaluati
  • n
  • fu
nc tio n) `(push (make-pre df un :name ,name :evaluatio n-f un cti
  • n
,evaluati
  • n
  • fu
nc ti
  • n)
*predicat e- fun ct ion s* )) Bad: w
  • rks
at expansion time (defmacr
  • defclass
(name &rest def) (setf (get name 'class) def) ... (list 'quote name)) 82
slide-83
SLIDE 83 4.4. Syntactic Abstraction Problems with Macros Bad: Macros should not eval a rgs (defmacr
  • add-person
(name mother father sex unevalua te d-a ge ) (let ((age (eval unevaluat ed
  • a
ge) )) (list (if (< age 16) ... ...) ...))) (add-per so n bob joanne jim male (compute-a ge 1953)) What if y
  • u
compiled this call no w and loaded it in a few y ea rs? Better: Let the compiler constant-fold (declaim (inline compute- age )) (defmacr
  • add-person
(name mother father sex age) `(funcal l (if (< ,age 16) ... ...) ...))) V ery Bad: (what if increment is n?) (defmacr
  • for
((variabl e start end &optional increment ) &body body) (if (not (numberp increment) ) (setf increment 1)) ...) (for (i 1 10) ...) 83
slide-84
SLIDE 84 4.4. Syntactic Abstraction Macros fo r Control Structures Go
  • d:
lls a hole in
  • rthogonalit
y
  • f
CL (defmacr
  • dovector
((var vector &key (start 0) end) &body body) "Do body with var bound to each element
  • f
vector. You can specify a subrange
  • f
the vector." `(block nil (map-vect
  • r
#'(lambda (,var) ,@body) ,vector :start start :end end))) (defun map-vect
  • r
(fn vector &key (start 0) end) "Call fn
  • n
each element
  • f
vector within a range." (loop for i from start below (or end (length vector)) do (funcall fn (aref vector-v ar index))))
  • Iterates
  • ver
a common data t yp e
  • F
  • llo
ws established syntax (dolist, dotimes)
  • Ob
eys decla rations, returns
  • Extends
established syntax with k eyw
  • rds
  • One
bad p
  • int:
No result as in dolist, dotimes 84
slide-85
SLIDE 85 4.4. Syntactic Abstraction Help er F unctions F
  • r
Macros Most macros should expand into a call to a function. The real w
  • rk
  • f
the macro dovector is done b y a func- tion, map-vector b ecause:
  • It's
easier to patch
  • It's
sepa rately callable (useful fo r p rogram)
  • The
resulting co de is smaller
  • If
p refered, the help er can b e made inline (Often go
  • d
to avoid consing closures) (dovecto r (x vect) (print x)) macro-expands to: (block nil (map-vect
  • r
#'(lambda (x) (print x)) vect :start :end nil)) which inline expands to (roughly): (loop for i from below (length vect) do (print (aref vect i))) 85
slide-86
SLIDE 86 4.4. Syntactic Abstraction Setf Metho ds As in macros, w e need to b e sure to evaluate each fo rm exactly
  • nce,
in left-to-right
  • rder.
Mak e sure macro expansions (macroexpan d, get-setf
  • me
th
  • d)
a re done in the right environment. (defmacr
  • deletef
(item sequence &rest keys &environ men t environmen t) "Destruc tiv el y delete item from sequence ." (multipl e-v al ue- bi nd (temps vals stores store-form access-for m) (get-setf
  • me
th
  • d
sequence environmen t) (assert (= (length stores) 1)) (let ((item-va r (gensym "ITEM"))) `(let* ((,item-va r ,item) ,@(mapcar #'list temps vals) (,(first stores) (delete ,item-var ,access-f
  • rm
,@keys)) ) ,store-for m) ))) 86
slide-87
SLIDE 87 5. Programmi ng in the La rge Programming in the La rge Be a w a re
  • f
stages
  • f
soft w a re development:
  • Gathering
requirements
  • Architecture
  • Comp
  • nent
Design
  • Implementation
  • Debugging
  • T
uning These can
  • verlap.
The p
  • int
  • f
explo rato ry p rogram- ming is to minim ize comp
  • nent
design time, getting quickly to implementati
  • n
in
  • rder
to decide if the a r- chitecture and requirements a re right. Kno w ho w to put together a la rge p rogram:
  • Using
pack ages
  • Using
defsystem
  • Sepa
rating source co de into les
  • Do
cumentation in the la rge
  • P
  • rtabilit
y
  • Erro
r handling
  • Interfacing
with non-Lisp p rograms 87
slide-88
SLIDE 88 5. Programmi ng in the La rge Sepa rating Source Co de into Files The follo wing facto rs aect ho w co de is decomp
  • sed
into les
  • Language-imp
  • sed
dep endencies macros, inline functions, CLOS classes b efo re use
  • Stratied
design isolate reusable comp
  • nents
  • F
unctional decomp
  • sition
group related comp
  • nents
  • Compatibili
t y with to
  • ls
chose go
  • d
size les fo r edito r, compile-f il e
  • Sepa
rate OS/machine/vendo r-sp ecic implem en- tations 88
slide-89
SLIDE 89 5. Programmi ng in the La rge Using Comments Eectively Use comments to/fo r:
  • Explain
philosophy . Don't just do cument de- tails; also do cument philosophy , motivation, and metapho rs that p rovide a framew
  • rk
fo r under- standing the
  • verall
structure
  • f
the co de.
  • Oer
examples. Sometimes an example is w
  • rth
a pile
  • f
do cumentation.
  • Have
conversations with
  • ther
develop ers! In a collab
  • rative
p roject, y
  • u
can sometimes ask a question just b y putting it in the source. Y
  • u
ma y come back to nd it answ ered. Leave the question and the answ er fo r
  • thers
who might later w
  • nder,
to
  • .
  • Maintain
y
  • ur
\to do" list. Put a sp ecial ma rk er
  • n
comments that y
  • u
w ant to return to later: ???
  • r
!!!; ma yb e use !!!! fo r higher p rio rit y . Some p rojects k eep to do lists and change logs in les that a re sepa rate from the source co de. (defun factoria l (n) ;; !!! What about negative numbers?
  • -Joe
03-Aug-9 3 ;; !!! And what about non-numb ers ??
  • Bill
08-Aug-9 3 (if (= n 0) 1 (* n (factoria l (- n 1))))) 89
slide-90
SLIDE 90 5. Programmi ng in the La rge Do cumentation: Sa y What Y
  • u
Mean Q: Do y
  • u
ever use comments when y
  • u
write co de? \Ra rely , except at the b eginning
  • f
p ro cedures, and then I
  • nly
comment
  • n
the data structure. I don't comments
  • n
the co de itself b ecause I feel that p rop- erly written co de is very self-do cumented." { Ga ry Kildall \I gure there a re t w
  • t
yp es
  • f
comments:
  • ne
is ex- plaining the
  • bvious,
and those a re w
  • rse
than w
  • rth-
less, the
  • ther
kind is when y
  • u
explain really involved, convoluted co de. W ell. I alw a ys try to avoid convo- luted co de. I try to p rogram really strong, clea r, clean co de, even if it mak es an extra ve lines. I am almost
  • f
the
  • pinion
that the mo re comments y
  • u
need, the w
  • rse
y
  • ur
p rogram is and something is wrong with it." { W a yne Ratli \Don't comment bad co de|rewrite it." { Kernighan & Plauger
  • Describ
e the purp
  • se
and structure
  • f
system
  • Describ
e each le
  • Describ
e each pack age
  • Do
cumentation strings fo r all functions
  • Consider
automatic to
  • ls
(manual)
  • Mak
e co de, not comments 90
slide-91
SLIDE 91 5. Programmi ng in the La rge Do cumentation: Over-comme nting These 32-lines must do cument a majo r system: ; ========= == == == == == == == == == == == == == == === == == == == == == == == == == == == == == ; ; describe ;
  • ;
; argument s : snepsul- ex p
  • <snepsul-
ex p> ; ; returns : <node set> ; ; descript io n : This calls "sneval " to evaluate "snepsu l- ex p" to ; get the desired <node set>. ; It prints the descripti
  • n
  • f
each <node> in the ; <node set> that has not yet been describe d during ; the process; the descript io n includes the ; descript io n
  • f
all <node>s dominate d by the <node>. ; It returns the <node set>. ; ; implemen ta ti
  • n
: Stores the <node>s which have already been describe d ; in "descri be
  • n
  • d
es ". ; Before tracing the descript io n
  • f
a <node>, it ; checks whether the <node> was already been describe d ; to avoid describ in g the same <node> repeate dl y. ; The variable "descri be- no de s" is updated by "des1". ; ; side-eff ec ts : Prints the <node>' s descripti
  • n
s. ; ; written: CCC 07/28/83 ; modified : CCC 09/26/83 ; ejm 10/10/83 ; njm 09/28/88 ; njm 4/27/89 91
slide-92
SLIDE 92 5. Programmi ng in the La rge Do cumentation: Over-comme nting (defmacr
  • describe
(&rest snepsul-e xp ) `(let* ((crntct (processco nt ex tde sc r ',snepsu l- exp )) (ns (in-conte xt .ns (nseval (getsndesc r ',snepsul
  • e
xp) ) crntct)) (described
  • no
de s (new.ns) ) (full nil)) (declare (special crntct described- no des full)) (terpri) (mapc #'(lambda (n) (if (not (ismemb. ns n described- no des )) (PP-nodet re e (des1 n)))) ns) (terpri) (values ns crntct))) Problems:
  • Do
cumentation to
  • long;
lose big picture
  • Do
cumentation is wrong: describ e(d)-no des.
  • Do
cumentation is ineective: no do c string
  • Do
cumentation is redundant (a rglist)
  • Bad
idea to shado w Lisp's describ e function
  • Need
function that is sepa rate from macro
  • Abb
reviations a re
  • bscure
92
slide-93
SLIDE 93 5. Programmi ng in the La rge Do cumentation: Commenting Better: This do esn't handle crntct (whatever that is) (defmacr
  • desc
(&rest snepsul- ex p) "Describ e the node referred to by this expressi
  • n.
This macro is intended as an interacti ve debugging tool; use the function describe- no de
  • se
t from a program. " `(descri be- no de- se t (exp->no de
  • se
t ',snepsul- ex p)) ) (defun describe
  • no
de
  • se
t (node-set) "Print all the nodes in this node set." ;; Accumula te described
  • no
de s to weed
  • ut
duplicat es . (let ((descri bed
  • n
  • de
s (new-node- se t)) ) (terpri) (dolist (node node-set) (unless (is-membe r- nod e- se t node describe d- nod es ) ;; des1 adds nodes to described- no des (pp-nodetr ee (des1 node described- nod es )) )) (terpri) node-set) ) 93
slide-94
SLIDE 94 5. Programmi ng in the La rge P
  • rtabilit
y Mak e y
  • ur
p rogram run w ell in the environment(s) y
  • u
use. But b e a w a re that y
  • u
  • r
someone else ma y w ant to use it in another environment someda y .
  • Use
#+feature and #-feature
  • Isolate
implementati
  • n-dep
endent pa rts.
  • Maintain
  • ne
source and multipl e bina ries
  • Evolve
to w a rds dpANS CL Implement missing features if needed
  • Be
a w a re
  • f
vendo r-sp ecic extensions 94
slide-95
SLIDE 95 5. Programmi ng in the La rge F
  • reign
F unction Interface La rge p rograms
  • ften
have to interface with
  • ther
p ro- grams written in
  • ther
languages. Unfo rtunately , there is no standa rd fo r this.
  • Lea
rn y
  • ur
vendo r's fo reign interface
  • T
ry to minimi ze exchange
  • f
data
  • Bew
a re
  • f
a reas that cause p roblems: Memo ry management Signal handling 95
slide-96
SLIDE 96 6. Miscellaneous Mean what y
  • u
sa y
  • Don't
mislead the reader Anticipate reader's misunderstandings
  • Use
the right level
  • f
sp ecicit y
  • Be
ca reful with decla rations Inco rrect decla rations can b reak co de
  • One-to-one
co rresp
  • ndence
Bad decla ration:
  • nly
made-up example (defun lookup (name) (declare (type string name)) (if (null name) nil (or (gethash name *symbol- tab le *) (make-symb
  • l-
en try name)))) Should b e (declare (type (or string null) name)) 96
slide-97
SLIDE 97 6. Miscellaneous Naming Conventions: Be Consistent Be consistent in names:
  • Be
consistent with capitalizati
  • n
most p refer like-thi s, not LikeThis
  • *special-v
ar iab le *
  • +constant+
(o r some convention)
  • Dylan
uses <class>
  • Consider
structure. sl
  • t
  • p
  • r
?; !
  • r
n;
  • >
  • r
  • to-
  • verb-object:
delete-f ile
  • bject-attribute:
integer- le ngt h compa re name-fil e and file-name don't use
  • bject-verb
  • r
attribute-object!
  • Order
a rguments consistently
  • Distinguish
internal and external functions Don't mix &optional and &key; use ca refully 1
  • r
2 &optional a rgs (Dylan 0) Use k eyw
  • rds
consistently (key, test, end) 97
slide-98
SLIDE 98 6. Miscellaneous Naming Conventions: Cho
  • se
Names Wisely Cho
  • se
Names wisely:
  • Minimize
abb reviations Most w
  • rds
have many p
  • ssible
abb reviations but
  • nly
  • ne
co rrect sp elling. Sp ell
  • ut
names so they a re easier to read, rememb er, and nd. Some p
  • ssible
exceptions: cha r, demo, intro, and pa ren. These w
  • rds
a re b ecoming almost lik e real w
  • rds
in English. A go
  • d
test (fo r native English sp eak ers) is: W
  • uld
y
  • u
sa y the w
  • rd
aloud in conversation? Our ea rlier example with crntct and processcon te xtd es cr w
  • uldn't
pass this test.
  • Don't
shado w a lo cal va riable with another.
  • Clea
rly sho w va riables that a re up dated.
  • Avoid
ambiguous names; Use previous
  • r
final instead
  • f
last. 98
slide-99
SLIDE 99 6. Miscellaneous Notational T ricks: P a rens in Column Most text edito rs treat a left pa ren in column as the sta rt
  • f
a top-level exp ression. A pa ren inside a string in column ma y confuse the edito r unless y
  • u
p rovide a backslash: (defun factoria l (n) "Compute the factorial
  • f
an integer. \(don't worry about non-intege r args)." (if (= n 0) 1 (* n (factoria l (- n 1))))) Many text edito rs will treat a "(def" in column as a denition, but not a "(def" in
  • ther
columns. So y
  • u
ma y need to do this: (progn (defun foo ...) (defun bar ...) ) 99
slide-100
SLIDE 100 6. Miscellaneous Multi-Line Strings In case
  • f
a multi-l i ne string as a literal constant, such as: (defun find-sub jec t- lin e (message-h ea der
  • s
tri ng ) (search " Subject: " message-he ade r- str in g) ) consider instead using read-time evaluation and a call to format: (defun find-sub jec t- lin e (message-h ea der
  • s
tri ng ) (search #.(format nil "~%Subje ct: ") message-h ea der
  • s
tri ng )) Where the same string is used many times, consider using a global va riable
  • r
named constant: (defpara me ter *subject- ma rke r* (format nil "~%Subjec t: ")) (defun find-sub jec t- lin e (message-h ea der
  • s
tri ng ) (search *subject-m ark er * message- he ade r- str in g) ) 100
slide-101
SLIDE 101 6. Miscellaneous Multi-Line Strings (cont'd) F
  • r
long fo rmat strings, y
  • u
can indent the continua- tion lines with <Return>
  • r
@<Return>. The follo wing t w
  • fo
rms do the same thing: (format t "~&This is a long string.~@ This is more
  • f
that string." ) This is a long string. This is more
  • f
that string. (format t "~&This is a long string.~ ~%This is more
  • f
that string." ) This is a long string. This is more
  • f
that string. The latter syntax p ermits y
  • u
to indent a xed amount easily: (format t "~&This is a long string.~ ~% This is more
  • f
that string, indented by
  • ne.")
This is a long string. This is more
  • f
that string, indented by
  • ne.
101
slide-102
SLIDE 102 6. Miscellaneous Notational T ricks: Multi-Line Comments Avoid using #| and |# in strings, since it will confuse any later attempt to comment
  • ut
such a string. Again, a backslash helps: Go
  • d:
(defun begin-co mme nt () (write-s tri ng "#\|")) (defun end-comm ent () (write-s tr ing "|\#")) This means that y
  • u
can later comment
  • ut
sections containing these strings without editing the strings them- selves. If y
  • ur
edito r p rovides supp
  • rt
(comment-region and uncomment-region commands) it is b etter to use ex- plicit ;; comments. That w a y the reader will never get confused ab
  • ut
which sections have b een commented
  • ut.
102
slide-103
SLIDE 103 6. Miscellaneous Some Red Flags The follo wing situations a re \red ags." They a re
  • f-
ten symptoms
  • f
p roblems|even though technically most
  • f
them do happ en in completely legitima te sit- uations as w ell. If y
  • u
see
  • ne
  • f
these red ags, y
  • u
do not automaticall y have a p roblem in y
  • ur
co de, but y
  • u
should still p ro ceed cautiously:
  • Any
use
  • f
eval
  • Any
use
  • f
gentemp *
  • Any
use
  • f
append
  • The
absence
  • f
an &environm en t pa rameter in a macro that uses setf
  • r
calls macroexpan d.
  • W
riting a condition handler fo r t yp e error (including use
  • f
ignore-err
  • rs
).
  • Any
use
  • f
the c...r functions except caar, cad...r, (where the \..." is all d's). * No kno wn go
  • d
uses. 103
slide-104
SLIDE 104 6. Miscellaneous Avoid Comm
  • n
Mistak es Go
  • d
st yle involves avoiding mistak es.
  • Alw
a ys p rompt fo r input (Or user w
  • n't
kno w what's happ ening)
  • Understand
defvar and defparamet er
  • Understand
flet and labels
  • Understand
multipl e values
  • Understand
macros (sho wn ab
  • ve)
  • Recompile
after changing macros
  • r
inline functions
  • Use
#'(lambda ...), not `(lambda ...)
  • Rememb
er #'f is just (functio n f)
  • Use
:test #'equal as needed
  • Mak
e sure decla rations a re eective
  • Have
a p
  • licy
fo r destructive functions 104
slide-105
SLIDE 105 6. Miscellaneous Destructive F unctions Have a p
  • licy
fo r destructive functions:
  • Most
p rograms use destructive up dates when they can p rove the a rguments a re not needed elsewhere (as when a function nconc's pa rtial results).
  • Otherwise,
assume that a rguments cannot b e al- tered
  • Assume
that results will not b e altered
  • Majo
r interfaces
  • ften
mak e copies
  • f
results they pass
  • ut,
just to b e safe.
  • Note
that generation scavenging GC can b e slo w ed do wn b y destructive up dates. 105
slide-106
SLIDE 106 6. Miscellaneous Mino r Mistak es Bad: (defun combine- ind ep
  • la
mb das (arc-exp ) (apply #'* (mapcar #'eval-a rc- ex p (cdr arc-exp))) )
  • apply
ma y exceed call-argum en ts- li mit
  • map
ca r generates ga rbage
  • cdr
violates data abstraction Go
  • d:
(reduce #'* (in-arcs arc-exp) :key #'eval-arc
  • e
xp ) Lea rn to use accumulato rs: (defun product (numbers &optiona l (key #'identi ty ) (accum 1)) "Like (reduce #'* numbers), but bails
  • ut
early when a zero is found." (if (null numbers) accum (let ((term (funcall key (first numbers)) )) (if (= term 0) (product (rest numbers) key (* accum term)))) Consider Series: (collect
  • f
n 'number (constantl y 1) #'* numbers) 106
slide-107
SLIDE 107 6. Miscellaneous Multi-T asking and Multi-Pro cessing Multi-T asking (Time Slicing) It is reasonable to sp end time structuring y
  • ur
co de to w
  • rk
w ell in the face
  • f
multi-task i ng. Many com- mercial Lisp implementati
  • ns
have this even though there is not y et a p
  • rtable
standa rd. It ts in w ell with existing language semantics.
  • W
atch
  • ut
fo r global state lik e setq and p rop ert y lists.
  • Synchronize
p ro cesses with without-in te rru pt s, without-ab
  • r
ts, without-p re emp ti
  • n,
etc. Consult implementati
  • n-sp
ecic do cumentation fo r the set
  • f
available
  • p
erato rs and lea rn ho w they dier. Multi-Pro cessing (T rue P a rallelism) Think ab
  • ut
true pa rallel i sm , but don't w aste a lot
  • f
time structuring y
  • ur
p rograms to w
  • rk
w ell if things suddenly b ecome pa rallel i zed. Making a sequential p ro- gram into a pa rallel
  • ne
is a non-trivial change that w
  • n't
happ en b y accident (e.g., due to some
  • vernight
change in Common Lisp's semantics). It will tak e a whole new language to supp
  • rt
this; y
  • u'll
have time to p repa re. 107
slide-108
SLIDE 108 6. Miscellaneous Exp ect The Unexp ected Murphy's La w \If something can go wrong, it will." Don't
  • mit
checking fo r things b ecause y
  • u're
sure something will never happ en unless y
  • u're
very sure. : : : And even then, don't
  • mit
them anyw a y . It is su- ciently commonplace to get erro rs from systems sa ying \This can't happ en" that it's clea r that p eople a re not alw a ys as b rilli a nt as they think. 108
slide-109
SLIDE 109 6. Miscellaneous Read Other P eople's Co de \Y
  • u
need to study
  • ther
p eople's w
  • rk.
Their ap- p roaches to p roblem solving and the to
  • ls
they use give y
  • u
a fresh w a y to lo
  • k
at y
  • ur
  • wn
w
  • rk."
{ Ga ry Kildall \I've lea rned a lot from lo
  • king
at
  • ther
p eople's p ro- grams." { Jonathan Sachs \I still think that
  • ne
  • f
the nest tests
  • f
p rogrammi ng abilit y is to hand the p rogramm er ab
  • ut
30 pages
  • f
co de and see ho w quickly he can read through and understand it." { Bill Gates \The b est w a y to p repa re [to b e a p rogrammer] is to write p rograms, and to study great p rograms that
  • ther
p eople have written. In my case, I w ent to the ga rbage cans at the Computer Science Center and I shed
  • ut
listings
  • f
their
  • p
erating system." { Bill Gates \Y
  • u've
got to b e willing to read
  • ther
p eople's co de, then write y
  • ur
  • wn,
then have
  • ther
p eople review y
  • ur
co de." { Bill Gates
  • Lisp
Machine Op erating System
  • Internet
FTP sites (comp.lang.lisp F A Q)
  • CMU
CL Compiler and Utiliti es
  • Macintosh
Common Lisp examples 109
slide-110
SLIDE 110 6. Miscellaneous Example: deftable T ask: Mak e it easy to dene and use tables.
  • Lik
e defstruct
  • Should
b e fast: inline functions
  • Should
handle
  • ne
  • r
multiple tables
  • CLOS?
  • Op
erations? Arguments and return value(s)?
  • Default
values? Mutated
  • r
returned? Sepa ration b et w een user and implemento r co de, with supp
  • rt
fo r b
  • th.
  • W
a y to dene new table implementati
  • ns
  • Naming;
pack ages?
  • Do
cumented limi tati
  • ns?
  • Instrumentation?
  • Automatic
selection? Lessons lea rned:
  • Capture
common abstractions: tables,
  • thers?
  • Complex
macros can b e designed with a little ca re
  • Consider
the p
  • ssibilit
y
  • f
extension 110
slide-111
SLIDE 111 6. Miscellaneous Protot yp e Lisp allo ws y
  • u
to develop p rotot yp es easily . \Plan to thro w
  • ne
a w a y; y
  • u
will, anyho w." { F red Bro
  • ks
\I think a lot b efo re I do anything, and
  • nce
I do some- thing, I'm not afraid to thro w it a w a y . It's very imp
  • r-
tant that a p rogramm er b e able to lo
  • k
back at a piece
  • f
co de lik e a bad chapter in a b
  • k
and scrap it with-
  • ut
lo
  • king
back." { John W a rno ck \Don't bind ea rly; don't ever mak e decisions ea rlier than y
  • u
have to. Sta y an
  • rder
  • f
magnitude mo re general than y
  • u
think y
  • u
need, b ecause y
  • u
will end up needing it in the long term. Get something w
  • rking
very quickly and then b e able to thro w it a w a y ." { John W a rno ck \So I tend to write a few lines at a time and try it
  • ut,
get it to w
  • rk,
then write a few mo re lines. I try to do the least amount
  • f
w
  • rk
p er iteration to mak e real substantive change." { W a yne Ratli \1-2-3 b egan with a w
  • rking
p rogram, and it continued to b e a w
  • rking
p rogram throughout its development." { Jonathan Sachs 111
slide-112
SLIDE 112 6. Miscellaneous Other Ideas Lea rn to t yp e. If y
  • u
t yp e less than 60 wpm, y
  • u're
holding y
  • urself
back. \Also, while y
  • u're
w
  • rking
ha rd
  • n
a complicated p ro- gram, it's imp
  • rtant
to exercise. The lack
  • f
physical exercise do es most p rogrammers in. It causes a loss
  • f
mental acuit y ." { John P age Q: What do es it tak e to b ecome a great p rogramm er? \What do es it tak e to b e go
  • d
at anything? What do es it tak e to b e a go
  • d
writer? Someone who's go
  • d
is a combination
  • f
t w
  • facto
rs: an accidental mental co r- resp
  • ndence
to the needs
  • f
the discipli nes, combined with a mental abilit y to not b e stupid. That's a ra re combination, but it's not at all mystical. A go
  • d
p ro- grammer must enjo y p rogramm ing and b e interested in it, so he will try to lea rn mo re. A go
  • d
p rogrammer also needs an aesthetic sense, combined with a guilt complex, and a k een a w a reness
  • f
when to violate that aesthetic sense. The guilt complex fo rces him to w
  • rk
ha rder to imp rove the p rogram and to b ring it mo re in line with the aesthetic sense." { Bob F rankston 112
slide-113
SLIDE 113 6. Miscellaneous Recommended Bo
  • ks
Intro ductions to Common Lisp
  • Rob
ert Wilensky Common LISPcraft
  • Deb
  • rah
G. T ata r A Programmer's Guide to Com- mon Lisp
  • Ro
dney A. Bro
  • ks.
Programmi ng in Common Lisp References and a Must-Have
  • Guy
L. Steele Common Lisp: The Language, 2nd Edition
  • ANSI
Draft Prop
  • sed
Common Lisp Standa rd
  • Ha
rold Ab elson and Gerald Ja y Sussman, with Julie Sussman. Structure and Interp retation
  • f
Com- puter Programs (Scheme) 113
slide-114
SLIDE 114 6. Miscellaneous Recommended Bo
  • ks
Mo re Advanced:
  • P
atrick H. Winston and Berthold K. P . Ho rn. LISP, 3rd edition.
  • W
ade L. Hennessey Common Lisp
  • Sony
a E. Keene Object-Oriented Programmi ng in Common Lisp: A Programmer's Guide to CLOS
  • Eugene
Cha rniak, Christopher K. Riesb eck, Drew V. McDermott and James R. Meehan. Articial Intelligence Programmi ng, 2nd edition.
  • P
eter No rvig. P a radigms
  • f
AI Programmi ng: Case Studies in Common Lisp P erio dicals:
  • LISP
P
  • inters.
(A CM SIGPLAN) Since 1987.
  • LISP
and Symb
  • lic
Computation. Since 1989.
  • Pro
ceedings
  • f
the biannual A CM Lisp and F unc- tional Programmi ng Conference. Since 1980. 114
slide-115
SLIDE 115 6. Miscellaneous Quotes Quotes from Programmers at W
  • rk,
Susan Lammers, Microsoft Press, 1989.
  • Bob
F rankston: Soft w a re Arts VisiCalc; Lotus
  • Bill
Gates: Altair BASIC; Microsoft
  • Ga
ry Kildall : Digital Resea rch CP/M
  • Scott
Kim: Stanfo rd, Xero x; Inversions
  • Butler
Lampson: Xero x Ethernet, Alto, Do rado, Sta r, Mesa; DEC
  • John
P age: HP; Soft w a re Publishing PFS:FILE
  • W
a yne Ratli: NASA; Ashton-T ate dBASE I I
  • Jonathan
Sachs: MIT; Lotus 1-2-3
  • Cha
rles Simonyi: Xero x Bravo; Microsoft W
  • rd,
Excel
  • John
W a rno ck: NASA; Xero x; Adob e P
  • stScript
115
slide-116
SLIDE 116 6. Miscellaneous Quotes Other quotes:
  • Ha
rold Ab elson: MIT; SICP; Logo
  • Judy
Anderson: Ha rlequin, Inc.
  • F
red Bro
  • ks:
IBM 360 a rchitect, no w at UNC
  • Bea
r Bry ant: Alabama fo
  • tball
coach
  • Brian
Kernighan & P .J. Plauger: Bell Labs UNIX
  • David
McDonald: MIT, UMass natural language generation
  • Guy
Steele: Thinking Machines; Scheme; CLtL
  • Gerald
Sussman: MIT; SICP; Scheme
  • Deb
  • rah
T ata r: DEC; Xero x; autho r
  • Niklaus
Wirth: ETH Zurich; P ascal Almost all Bad Co de examples a re tak en from published b
  • ks
and a rticles (whose autho rs should kno w b etter, but will remain anonymous). 116