<<

Lisp Users and Vendors Conference

August

Tutorial on

Go o d Lisp Programming

Style

Peter Norvig

Sun Microsystems Labs Inc

Kent Pitman

Harlequin Inc

Portions copyright Peter Norvig

c

Portions copyright Kent M Pitman

All Rights Reserved

Outline

What is Go o d Style

Tips on BuiltIn Functionality

Tips on NearStandard Tools

Kinds of Abstraction

Programming in the Large

Miscellaneous

What is Go o d Style

Good Lisp Programming Style

Elegance is not optional Richard A OKeefe

Good style in any language leads to programs that

are

Understandable

Reusable

Extensible

Ecient

Easy to developdebug

It also helps correctness robustness compatibility

Our maxims of go o d style are

Be explicit

Be sp ecic

Be concise

Be consistent

Be helpful anticipate the readers needs

Be conventional don b e obscure

Build abstractions at a usable level

Allow to ols to interact referential transparency

Good style is the underware that supp ortsaprogram

Where do es go o d style come from

What To Believe

Dont b elieve everything we tell you Just most

Worry less ab out what to b elieve and more ab out why

Know where your Style Rules come from

Religion Go o d vs Evil This way is b etter

Philosophy This is consistent with other things

Robustness Liability Safety Ethics Ill put in

redundant checks to avoid something horrible

Legality Our lawyers say do it this way

Personality Opinion I like it this way

Compatibility Another to ol exp ects this way

Portability Other prefer this way

Co op eration Convention It has to be done

some uniform waysowe agreed on this one

Habit Tradition Weve always done it this way

Ability My arent sophisticated enough

Memory Knowing how I would do it means I

dont have to rememb er howIdid do it

Sup erstition Im scared to do it dierently

Practicality This makes other things easier

Where do es go o d style come from

Its All Ab out Communication

Expression Understanding Communication

Programs communicate with

Human readers

Compilers

Text editors arglist do c string indent

To ols trace step aprop os xref manual

Users of the program indirect communication

Where do es go o d style come from

Know the Context

When reading co de

Know who wrote it and when

When writing co de

Annotate it with comments

Sign and date your comments

Should b e an editor command to do this

Some things to notice

Peoples style changes over time

The same p erson at dierent times can seem like

a dierent p erson

Sometimes that p erson is you

How do I knowifitsgood

Value Systems Are Not Absolute

Style rules cannot b e viewed in isolation

They often overlap in conicting ways

The fact that style rules conict with one another re

ects the natural fact that realworld goals conict

A good makes tradeos in programming

style that reect underlying priority choices among var

ious major goals

Understandable

Reusable

Extensible

Ecient co ding space sp eed

Easy to developdebug

How do I knowifitsgood

Why Go o d Style is Go o d

Good style helps build the current program and the

one

Organizes a program relieving human memory needs

Encourages mo dular reusable parts

Style is not just added at the end It plays a part in

Organization of the program into les

Toplevel design structure and layout of each le

Decomp osition into mo dules and comp onents

Datastructure choice

Individual function designimplementation

Naming formatting and do cumenting standards

How do I knowifitsgood

Why Style is Practical Memory

When I was young I could imagine a castle with

twenty ro oms with each ro om having ten dierent ob

jects in it I would have no problem I cant do that

anymore Now I think more in terms of earlier exp eri

ences I see a network of inchoate clouds instead of

the picturep ostcard clearness But I do write b etter

programs Charles Simonyi

Some p eople are go o d programmers b ecause they can

handle many more details than most p eople But there

are a lot of disadvantages in selecting programmers for

that reasonit can result in programs no on else can

maintain Butler Lampson

Pick out any three lines in my program and I can tell

you where theyre from and what they do David

McDonald

Good style replaces the need for great memory

Make sure any lines are selfexplanatory

Also called referential transparency

Package complexity into objects and abstractions

not global variablesdep endencies

Make it fractally selforganizing all the way updown

Saywhatyou mean

Mean what you say

How do I knowifitsgood

Why Style is Practical Reuse

Structured Programming encourages mo dules that meet

sp ecications and can b e reused within the b ounds of

that sp ecication

Stratied Design encourages mo dules with commonly

needed functionality which can be reused even when

the sp ecication changes or in another program

ObjectOriented Design is stratied design that con

centrates on classes of objects and on information hid

ing

You should aim to reuse

Data typ es classes

Functions metho ds

Control abstractions

Interface abstractions packages mo dules

Syntactic abstractions macros and whole languages

How do I knowifitsgood

Say What You Mean

Saywhatyou mean simply and directly Kernighan

Plauger

Say what you mean in data b e sp ecic concise

Use data abstractions

Dene languages for data if needed

Cho ose names wisely

Say what you mean in co de b e concise conventional

Dene interfaces clearly

Use Macros and languages appropriately

Use builtin functions

Create your own abstractions

Dont do it twice if you can do it once

In annotations b e explicit helpful

Use appropriate detail for comments

Do cumentation strings are b etter than comments

Saywhatitisfor not just what it do es

Declarations and assertions

Systems and test les etc

How do I knowifitsgood

Be Explicit

Optional and Keyword arguments

If you have to lo ok up the default value you need to

supply it You should only take the default if you truly

b elieve you dont care or if youre sure the default is

wellundersto o d and wellaccepted byall

For example when op ening a le you should almost

never consider omitting the direction keyword argu

ment even though you know it will default to input

Declarations

If you knowtyp e information declare it Dont do what

some p eople do and only declare things you know the

will use Compilers change and you want your

program to naturally take advantage of those changes

without the need for ongoing intervention

Also declarations are for communication with human

readers to onot just compilers

Comments

If youre thinking of something useful that others might

want to know when they read your co de and that might

not b e instantly apparent to them make it a comment

How do I knowifitsgood

Be Sp ecic

Be as sp ecic as your data abstractions warrant

but no more

Cho ose

more specific more abstract

mapc processword map nil processword

first sentences elt sentences

Most sp ecic conditional

if fortwobranch expression

when unless foronebranch statement

and or for b o olean value only

cond for multibranch statement or expression

Violates Expectation Follows Expectation

and numberp x cos x and numberp x x

if numberp x cos x if numberp x cos x nil

if numberp x print x when numberp x print x

How do I knowifitsgood

Be Concise

Test for the simplest case If you make the same test

or return the same result in two places there must

b e an easier way

Bad verb ose convoluted

defun countallnumbers alist

cond

null alist

t if listp first alist

countallnumbers first alist

if numberp first alist

countallnumbers rest alist

Returns twice

Nonstandard indentation

alist suggests asso ciation list

Good

defun countallnumbers exp

typecase exp

countallnumbers first exp

countallnumbers rest exp

number

t

cond instead of typecase is equally go o d less sp ecic

more conventional consistent

How do I knowifitsgood

Be Concise

Maximize LOCNW lines of co de not written

Shorter is b etter and shortest is b est

Jim Meehan

Bad to o verb ose inecient

defun vectoradd x y

let z nil n

setq n min listlength x listlength y

dotimes j n reverse z

setq z cons nth j x nth j y z

defun matrixadd A B

let C nil m

setq m min listlength A listlength B

dotimes i m reverse C

setq C cons vectoradd nth i A

nth i B C

Use of nth makes this O n

Why listlength Why not length or mapcar

Why not nreverse

Why not use arrays to implement arrays

The return value is hidden

How do I knowifitsgood

Be Concise

Better more concise

defun vectoradd x y

Elementwise add of two vectors

mapcar x y

defun matrixadd A B

Elementwise add of two matrices lists of lists

mapcar vectoradd A B

Or use generic functions

defun add rest args

Generic addition

if null args

reduce binaryadd args

defmethod binaryadd x number y number

x y

defmethod binaryadd x sequence y sequence

map typeof x binaryadd x y

How do I knowifitsgood

Be Helpful

Do cumentation should b e organized around tasks the

user needs to do not around what your program hap

p ens to provide Adding do cumentation strings to each

function usually do esnt tell the reader how to use your

program but hints in the right place can be very ef

fective

Good from Gnu online help

nextline Move cursor vertically down ARG lines

If you are thinking of usingthisinaLispprogram

consider using forwardline instead It is usually eas

ier to use and more reliable no dep endence on goal

column etc

defun denes NAME as a function The denition

is lambda ARGLIST DOCSTRING BODY See also the

function interactive

These anticipate users use and problems

How do I knowifitsgood

Be Conventional

Build your own functionalitytoparallel existing features

Ob ey naming conventions

withsomething dosomething macros

Use builtin functionality when p ossible

Conventional reader will know what you mean

Concise reader do esnt have to parse the co de

Ecient has b een worked on heavily

Bad nonconventional

defun addtolist elt list

cond member elt lst lst

t cons elt lst

Good use a builtin function

left as an exercise

Use library functions Kernighan Plauger

How do I knowifitsgood

Be Consistent

Some pairs of op erators have overlapping capabilities

Be consistent ab out which you use in neutral cases

where either can b e used so that it is apparent when

youre doing something unusual

Here are examples involving let and let The rst

exploits parallel binding and the second sequential The

third is neutral

let a b b a

let a b b a c b

let a x y b y x

Here are analogous examples using flet and labels

The rst exploits closure over the lo cal function the

second exploits nonclosure The third is neutral

labels process x process cdr x

flet foo x foo x

flet add x x

In b oth cases you could cho ose things the other way

around always using let or labels in the neutral case

and let or flet in the unusual case Consistency mat

ters more than the actual choice Most p eople how

ever think of let and flet as the normal choices

How do I knowifitsgood

Cho ose the Right Language

Cho ose the appropriate language and use appropriate

features in the language you cho ose Lisp is not the

right language foreveryproblem

You got to dance with the one that brung you

BearBryant

Lisp is go o d for

Exploratory programming

Rapid prototyping

Minimizing timetomarket

Singleprogrammer or singledigit team projects

Sourcetosource or datatodata transformation

Compilers and other translators

Problemsp ecic languages

Dynamic dispatch and creation

compiler available at runtime

Tight integration of mo dules in one image

as opp osed to s character pip e mo del

High degree of interaction readevalprint CLIM

Userextensible applications gnu emacs

I b elieve good software is written by small teams of

two three or four p eople interacting with each other

at a very high dense level John Warno ck

How do I knowifitsgood

Cho ose the Right Language

Once you are an exp erienced Lisp programmer its

hard to return to any other language Rob ert R

Kessler

Current Lisp implementations are not so go o d for

Persistent storage data base

Maximizing resource use on small machines

Projects with hundreds of programmers

Close communication with foreign co de

Delivering smallimage applications

Realtime control but Gensym did it

Projects with inexp erienced Lisp programmers

Some kinds of numerical or character computation

Works ne with careful declarations but the Lisp

eciency mo del is hard to learn

Tips on Builtin Functionality

Builtin Functionality

No doubt ab out it is a big language

Guy Steele

builtin functions in one preANSI CL

macros

sp ecial forms

variables

constants

But what counts as the language itself

C has reserved words

ANSI CL is down to sp ecial forms

The rest can b e thought of as a required library

Either way the Lisp programmer needs some help

Which builtin functionality to makeuseof

How to use it

Tips on Builtin Functionality

DEFVAR and DEFPARAMETER

Use defvar for things you dont want to reinitialize

up on reload

defvar options

defun addoption x pushnew x options

Here you might have done addoption many

times b efore you reload the lep erhaps some even

from another le You usually dont want to throw

away all that data just b ecause you reload this deni

tion

On the other hand some kinds of options do want to

get reinitialized up on reload

defparameter useexperimentalmode nil

Set this to T when experimental code works

Later you might edit this le and set the variable to T

and then reload it wanting to see the eect of your

edits

Recommendation Ignore the part in CLtL that says

defvar is forvariables and defparameter is forparame

ters The only useful dierence b etween these is that

defvar do es its assignment only if the variable is un

b ound while defparameter do es its assignment uncon

ditionally

Tips on Builtin Functionality

EVALWHEN

evalwhen execute

evalwhen compiletoplevel

evalwhen loadtoplevel

Also takecare ab out explicitly nesting evalwhen forms

The eect is not generally intuitive for most p eople

Tips on Builtin Functionality

FLET to Avoid Co de Duplication

Consider the following examples duplicated use of

f g h

do x f g h

f g h

nil

Every time you edit one of the f g hs you prob

abywant to edit the other to o Here is a b etter mo d

ularity

flet fgh f g h

do x fgh fgh nil

This might b e used as an argument against do

Similarlyyou might use lo cal functions to avoid dupli

cation in co de branches that dier only in their dynamic

state For example

defmacro handlercaseif test form rest cases

let doit gensym DOIT

flet doit form

if test

handlercase doit cases

doit

Tips on Builtin Functionality

DEFPACKAGE

Programming in the large is supp orted byadesignstyle

that separates co de into mo dules with clearly dened

interfaces

The Common Lisp package system serves to avoid

name clashes b etween mo dules and to dene the in

terface to each mo dule

There is no top level b e threadsafe

There are other programs use packages

Make it easy foryour consumers

Exp ort only what the consumer needs

Make it easy for maintainers

License to change nonexp orted part

defpackage PARSER

use LISP Lucid LCL Allegro EXCL

export PARSE PARSEFILE STARTPARSERWINDOW

DEFINEGRAMMAR DEFINETOKENIZER

Some put exp orted symb ols at the top of the le where

they are dened

We feel it is b etter to put them in the defpackageand

use the editor to nd the corresp onding denitions

Tips on Builtin Functionality

Understanding Conditions vs Errors

Lisp assures that most errors in co de will not corrupt

data byproviding an active condition system

Learn the dierence b etween errors and conditions

All errors are conditions not all conditions are errors

Distinguish three concepts

Signaling a condition

Detecting that something unusual has happ ened

Providing a restart

Establishing one of p ossibly several options for

continuing

Handling a condition

Selecting howtopro ceed from available options

Tips on Builtin Functionality

Error Detection

Pick a level of error detection and handling that matches

your intent Usually you dont want to let bad data go

by but in many cases you also dont want to b e in the

debugger for inconsequential reasons

Strike a balance b etween tolerance and pickiness that

is appropriate to your application

Bad what if its not an integer

defun parsedate string

Read a date from a string

multiplevaluebind dayofmonth stringposition

parseinteger string junkallowed t

Questionable what if memory runs out

ignoreerrors parsedate string

Better catches exp ected errors only

handlercase parsedate string

parseerror nil

Tips on Builtin Functionality

Writing Go o d Error Messages

Use full sentences in error messages upp ercase

initial trailing p erio d

No Error or prex The system will sup

ply such a prex if needed

Do not b egin an error message with a request for

a fresh line The system will do this automatically

if necessary

As with other format strings dont use emb edded

tab characters

Dont mention the consequences in the error mes

sage Just describ e the situation itself

Dont presupp ose the debuggers user interface in

describing how to continue This maycauseporta

bilityproblems since dierent implementations use

dierent interfaces Just describ e the abstract ef

fect of a given action

Sp ecify enough detail in the message to distinguish

it from other errors and if you can enough to help

you debug the problem later if it happ ens

Tips on Builtin Functionality

Writing Go o d Error Messages contd

Bad

error Error Foo Type C to continue

Better

cerror Specify a replacement sentence interactively

An illformed sentence was encountered A

sentence

Tips on Builtin Functionality

Using the Condition System

Start with these

error cerror

warn

handlercase

withsimplerestart

unwindprotect

Good standard use of warn

defvar word The word we are currently working on

defun lexwarn formatstr rest args

Lexical warning like warn but first tells what word

caused the warning

warn For word a word formatstr args

Tips on Builtin Functionality

HANDLERCASE WITHSIMPLERESTART

Good handle sp ecic errors

defun evalexp exp

If possible evaluate this exp otherwise return it

Guard against errors in evaluating exp

handlercase

if and fboundp op exp

every isconstant args exp

eval exp

exp

arithmeticerror exp

Good provide restarts

defun toplevel key prompt read read

eval eval print print

A readevalprint loop

withsimplerestart

abort Exit out of the top level

loop

withsimplerestart

abort Return to top level loop

format t a prompt

funcall print funcall eval funcall read

Tips on Builtin Functionality

UNWINDPROTECT

unwindprotect implements imp ortant functionality that

everyone should knowhowtouse It is not just for sys

tem programmers

Watch out for multitasking though For example im

plementing some kinds of statebinding with unwindprotect

might work well in a singlethreaded environment but

in an environment with multitasking you often have

to b e a little more careful

unwindprotect progn form form form

n

cleanup cleanup cleanup

n

Never assume form will get run at all

Never assume form wont run to completion

n

Tips on Builtin Functionality

UNWINDPROTECT contd

Often you need to save state b efore entering the unwindprotect

and test b efore you restore state

Possibly Bad with multitasking

catch robotop

unwindprotect

progn turnonmotor

manipulate

turnoffmotor

Good safer

catch robotop

let status motorstatus motor

unwindprotect

progn turnonmotor motor

manipulate motor

when motoron motor

turnoffmotor motor

setf motorstatus motor status

Tips on Builtin Functionality

IO Issues Using FORMAT

Dont use Tab characters in format strings or any

strings intended for output Dep ending on what

column your output starts in the tab stops may

not line up the same on output as they did in the

co de

Dont use S A to print unreadable objects

Use printunreadableobject instead

Consider putting format directives in upp ercase to

make them stand out from lowercase text sur

rounding

For example Foo A instead of Foo a

Learn useful idioms For example A and

p

Be conscious of when to use versus

Also and are also handy

Most co de which outputs a single line should start

with and end with

format t This is a test

This is a test

Be aware of implementation extensions They may

not b e p ortable but for nonp ortable co de might

b e very useful For example Generas  and 

for handling indentation

Tips on Builtin Functionality

Using Streams Correctly

standardoutput and standardinput vs terminalio

Do not assume standardinput and standardoutput

will b e b ound to terminalio or in fact to any

interactive stream You can bind them to such a

stream however

Try not to use terminalio directly for input or

output It is primarily available as a stream to

which other streams maybe b ound ormayindi

rect eg by synonym streams

erroroutput vs debugio

Use erroroutput for warnings and error mes

sages that are not accompanied by any user inter

action

Use debugio for interactive warnings error mes

sages and other interactions not related to the

normal function of a program

In particular do not rst print a message on erroroutput

and then do a debugging session on debugioex

p ecting those to b e the same stream Instead do

each interaction consistently on one stream

Tips on Builtin Functionality

Using Streams Correctly contd

traceoutput

This can b e used formore than just receiving the

output of trace If you write debugging routines

that conditionally print helpful information with

out stopping your running program consider do

ing output to this stream so that if traceoutput

is redirected your debugging output will to o

A useful test If someone reb ound only one of several

IO streams you are using would it makeyour output

lo ok stupid

Tips on NearStandard Tools

Using NearStandard To ols

Some functionality is not built in to the language but

is used by most programmers This divides into exten

sions to the language and to ols that help you develop

programs

Extensions

defsystem to dene a program

CLIM CLX etc graphics libraries

To ols

emacs from FSF Lucid

indentation fontcolorsupport

denitionarglistdo cregexp nding

communication with lisp

xref manual etc from CMU

Browsers debuggers prolers from vendors

Tips on NearStandard Tools

DEFSYSTEM

Pick a public domain version of defsystem unfortu

nately dpANS CL has no standard

Put absolute pathnames in one place only

Load everything through the defsystem

Distinguish compiling from loading

Optionally do version control

defpackage PARSER

defsystem parser

source labindexingparser

parts utilities macros grammar tokenizer

optimizer debugger toplevel

CLIM climgraphics CLX graphics

Make sure your system loads with no compiler

warnings

rst time and subsequent times

learn to use declare ignore

Make sure the system can b e compiled from scratch

eliminate lingering b o otstrapping problems

Tips on NearStandard Tools

Editor Commands

Your editor should b e able to do the following

Move ab out by sexpressions and show matching

parens

Indent co de prop erly

Find unbalanced parens

Adorn co de with fonts and colors

Find the denition of any symb ol

Find arguments or do cumentation for any symb ol

Macro expand any expression

Send the current expression region or le to Lisp

to b e evaluated or compiled

Keep a history of commands sent to Lisp and allow

you to edit and resend them

Work with keyb oard mouse and menus

Emacs can do all these things If your editor cant

complain until it is xed or get a new one

Tips on NearStandard Tools

Emacs Indentation and Comments

Dont try to indent yourself

Instead let the editor do it

Anearstandard form has evolved

column maximum width

Ob ey comment conventions

for inline comment

for infunction comment

forbetweenfunction comment

for section header for outline mo de

clindent library can b e told how to indent

put defvar commonlispindentfunction

lemacs can provide fonts color

hilitmodeslistupdate Lisp

nil hilit

Abstraction

Abstraction

All programming languages allow the programmer to

dene abstractions All mo dern languages provide sup

port for

Data Abstraction abstract data typ es

Functional Abstraction functions pro cedures

Lisp and other languages with closures eg ML Sather

supp ort

Control Abstraction dening iterators and other

new ow of control constructs

Lisp is unique in the degree to which it supp orts

Syntactic Abstraction macros whole new lan

guages

Abstraction

Design Where Style Begins

The most imp ortant part of writing a program is de

signing the data structures The second most imp or

tant part is breaking the various co de pieces down

Bill Gates

Exp ert engineers stratify complex designs The

parts constructed at each level are used as primitives

at the next level Each level of a stratied design can

b e thought of as a sp ecialized language with a variety

of primitives and means of combination appropriate to

that level of detail Harold Ab elson and Gerald

Sussman

Decomp ose decisions as much as p ossible Untangle

asp ects which are only seemingly indep endent Defer

those decisions which concern details of representation

as long as p ossible Niklaus Wirth

Lisp supp orts all these approaches

Data Abstraction classes structures deftyp e

Functional Abstraction functions metho ds

Interface Abstraction packages closures

ObjectOriented CLOS closures

Stratied Design closures all of ab ove

Delayed Decisions runtime dispatch

Abstraction

Design Decomp osition

A Lisp pro cedure is likea paragraph

Deb orah Tatar

You should b e able to explain any mo dule in one sen

tence Wayne Ratli

Strive for simple designs

Break the problem into parts

Design useful subparts stratied

Be opp ortunistic use existing to ols

Determine dep endencies

Remo dularize to reduce dep endencies

Design most dep endent parts rst

We will cover the following kinds of abstraction

Data abstraction

Functional abstraction

Control abstraction

Syntactic abstraction

Data Abstraction

Data Abstraction

Write co de in terms of the problems data typ es not

the typ es that happ en to b e in the implementation

Use defstruct or defclass for record typ es

Use inline functions as aliases not macros

Use deftype

Use declarations and type slots

for eciency andor do cumentation

Variable names give informal typ e information

Pretty Good sp ecies some typ e info

defclass event

startingtime type integer

location type location

duration type integer initform

Better problemsp ecic typ e info

deftype time Time in seconds integer

defconstant thedawnoftime

Midnight January

defclass event

startingtime type time initform thedawnoftime

location type location

duration type time initform

Data Abstraction

Use Abstract Data Typ es

Intro duce abstract data typ es with accessors

Bad obscure accessor eval

if eval cadar rules

Better intro duce names for accessors

declaim inline ruleantecedent

defun ruleantecedent rule second rule

if holds ruleantecedent first rules

Usually Best intro duce rstclass data typ e

defstruct rule

name antecedent consequent

or

defstruct rule type list

name antecedent consequent

or

defclass rule

name antecedent consequent

Data Abstraction

Implement Abstract Data Typ es

Knowhow to map from common abstract data typ es

to Lisp implementations

Set list bitvector integer any table typ e

Sequence list vector delayedevaluation stream

Stack list vector with llp ointer

Queue tconc vector with llp ointer

Table hash table alist plist vector

Tree Graph cons structures vector adjacency

matrix

Use implementations that are already supp orted eg

union intersection length for sets as lists logior

logand logcount for sets as integers

Dont b e afraid to build a new implementation if pro

ling reveals a b ottleneck If Common Lisps hash

tables are to o inecient foryour application consider

building a sp ecialized hash table in Lisp b efore you build

a sp ecialized hash table in C

Data Abstraction

Inherit from Data Typ es

Reuse by inheritance as wellasdirectuse

structures supp ort single inheritance

classes supp ort multiple inheritance

b oth allow some overriding

classes supp ort mixins

Consider a class or structure for the whole program

Eliminates clutter of global variables

Threadsafe

Can b e inherited and mo died

Functional Abstraction

Functional Abstraction

Every function should have

A single sp ecic purp ose

If p ossible a generally useful purp ose

A meaningful name

names like recurseaux indicate problems

A structure that is simple to understand

An interface that is simple yet general enough

As few dep endencies as p ossible

A do cumentation string

Functional Abstraction

Decomp osition

Decomp ose an algorithm into functions that are simple

meaningful and useful

Example from complanglisp discussion of loop vs map

defun leastcommonsuperclass instances

let candidates

reduce intersection

mapcar lambda instance

closclassprecedencelist

classof instance

instances

bestcandidate findclass t

mapl

lambda candidates

let currentcandidate first candidates

remainingcandidates rest candidates

when and subtypep currentcandidate

bestcandidate

every

lambda remainingcandidate

subtypep currentcandidate

remainingcandidate

remainingcandidates

setf bestcandidate currentcandidate

candidates

bestcandidate

Functional Abstraction

Decomp osition

Very Good Chris Riesb eck

defun leastcommonsuperclass instances

reduce morespecificclass

commonsuperclasses instances

initialvalue findclass t

defun commonsuperclasses instances

reduce intersection

superclasslists instances

defun superclasslists instances

loop for instance in instances

collect closclassprecedencelist

classof instance

defun morespecificclass class class

if subtypep class class class class

Each function is very understandable

Control structure is clear

Two reduces an intersection and a lo opcollect

But reusablity is fairly low

Functional Abstraction

Decomp osition

Equally Go o d and more reusable

defun leastcommonsuperclass instances

Find a least class that all instances belong to

leastupperbound mapcar classof instances

closclassprecedencelist

subtypep

defun leastupperbound elements supers sub

Element of lattice that is a super of all elements

reduce lambda x y

binaryleastupperbound x y supers sub

elements

defun binaryleastupperbound x y supers sub

Least upper bound of two elements

reduceif sub intersection funcall supers x

funcall supers y

defun reduceif pred sequence

Eg reduceif numbers computes maximum

reduce lambda x y if funcall pred x y x y

sequence

Individual functions remain understandable

Still reduces an intersection and a map car

Stratied design yields more useful functions

Functional Abstraction

Rule of English Translation

To insure that you saywhatyou mean

Start with an English description of algorithm

Write the co de from the description

Translate the co de back into English

Compare to

Example

Given a list of monsters determine the numb er

that are swarms

defun countswarm monsterlist

apply

mapcar

lambda monster

if equal objecttype

getobject monster

swarm

monsterlist

Take the list of monsters and pro duce a for

a monster whose typ e is swarm and a for the

others Then add up the list of numb ers

Functional Abstraction

Rule of English Translation

Better

Given a list of monsters determine the numb er

that are swarms

defun countswarms monsternames

Count the swarms in a list of monster names

countif swarmp monsternames key getobject

or

count swarm monsternames key getobjecttype

or

loop for name in monsternames

count swarmp getobject monster

Given a list of monster names count the numb er

that are swarms

Functional Abstraction

Use Library Functions

Libraries may have access to lowlevel eciency hacks

and are often netuned

BUT they may b e to o general hence inecient

Write a sp ecic version when eciency is a problem

Good sp ecic concise

defun findcharacter char string

See if the character appears in the string

find char string

Good ecient

defun findcharacter char string

See if the character appears in the string

declare character char simplestring string

loop for ch across string

when eql ch char return ch

Functional Abstraction

Use Library Functions

Given build which maps n to a list of n xs

build  x x x x

Task Dene buildit so that

buildit  x x x x x x x

Incredibly Bad

defun round x

let result

dotimes n length x result

setq result cons car nthcdr n x result

defun buildit arglist

let result

dolist a round arglist result

setq result cons build a result

Problems

round is just another name for reverse

car nthcdr n x is nth n x

dolist would b e b etter than dotimes here

push would b e appropriate here

mapcar build numbers do es it all

Control Abstraction

Control Abstraction

Most algorithms can b e characterized as

Searching some find findif mismatch

Sorting sort merge removeduplicates

Filtering remove removeif mapcan

Mapping map mapcar mapc

Combining reduce mapcan

Counting count countif

These functions abstract common control patterns

Co de that uses them is

Concise

Selfdo cumenting

Easy to understand

Often reusable

Usually ecient

Better than a nontail recursion

Intro ducing your own control abstraction is an imp or

tant part of stratied design

Control Abstraction

Recursion vs Iteration

Recursion is go o d for recursive data structures Many

p eople prefer to view a list as a sequence and use iter

ation over it thus deemphasizing the implementation

detail that the list is split into a rst and rest

As an expressive style tail recursion is often considered

elegant However Common Lisp do es not guarantee

tail recursion elimination so it should not be used as

a substitute for iteration in completely p ortable co de

In Scheme it is ne

The Common Lisp do macro can b e thought of as syn

tactic sugarfor tail recursion where the initial values

forvariables are the argument values on the rst func

tion call and the step values are argument values for

subsequent function calls

do provides a low level of abstraction but versatile and

has a simple explicit execution mo del

Control Abstraction

Recursion vs Iteration contd

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 of list is true

some notnull list

or findifnot null lst

or loop for x in list thereis x

or explicit

do list list rest list

null list nil

when first list

return t

Best ecient most concise in this case

Dont call any at all

Use some p list instead of any mapcar p list

Control Abstraction

LOOP

Keep a loop to one topiclike a letter to your

Senator Judy Anderson

The Common Lisp loop macro gives you the p ower to

express idiomatic usages concisely However it bears

the burden that its syntax and semantics are often sub

stantially more complex than its alternatives

Whether or not to use the loop macro is an issue sur

rounded in controversyandborders on a religious war

At the ro ot of the conict is the following somewhat

paradoxical observation

loop app eals to naive programmers b ecause it lo oks

like English and seems to call for less knowledge

of programming than its alternatives

loop is not English its syntax and semantics have

subtle intricacies that have been the source of

many programming bugs It is often b est used

by p eople whove taken the time to study and un

derstand itusually not naive programmers

Use the unique features of lo op eg parallel iteration

of dierent kinds

Control Abstraction

Simple Iteration

Bad verb ose control structure unclear

LOOP

SETQ WORD POP SENTENCE get the next word

COND

if no more words then return instantiated CD form

which is stored in the variable CONCEPT

NULL WORD

RETURN REMOVEVARIABLES VARVALUE CONCEPT

T FORMAT T Processing A WORD

LOADDEF look up requests under

this word

RUNSTACK fire requests

No need for global variables

End test is misleading

Not immediately clear what is done to each word

Good conventional concise explicit

mapc processword sentence

removevariables varvalue concept

defun processword word

format t Processing A word

loaddef word

runstack

Control Abstraction

Mapping

Bad verb ose

extractidlist luserrecs lambda

WHERE luserrecs is a list of user records

RETURNS a list of all user ids in luserrecs

USES extractid

USED BY processusers sortusers

defun extractidlist userrecs

prog idlist

loop

cond null userrecs

idlist was constructed in reverse order

using cons so it must be reversed now

return nreverse idlist

setq idlist cons extractid car userrecs

idlist

setq userrecs cdr userrecs next user record

go loop

Good conventional concise

defun extractidlist userrecordlist

Return the user IDs for a list of users

mapcar extractid userrecordlist

Control Abstraction

Counting

Bad verb ose

defun size

prog size idx

setq size idx

loop

cond idx tablesize

setq size size length aref table idx

idx idx

go loop

return size

Good conventional concise

defun tablecount table Formerly called SIZE

Count the number of keys in a hashlike table

reduce table key length

Also it couldnt hurt to add

deftype table

A table is a vector of buckets where each bucket

holds an alist of key values pairs

vector cons

Control Abstraction

Filtering

Bad verb ose

defun removebadpredvisited l badpred closed

Returns a list of 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

removebadpredvisited

cdr l badpred closed

t cons car l

removebadpredvisited

cdr l badpred closed

Good conventional concise

defun removebadorclosednodes nodes badnode closed

Remove nodes that are bad or are on closed list

removeif lambda node

or funcall badnode node

member node closed

nodes

Control Abstraction

Control Flow Keep It Simple

Nonlo cal control owishard to understand

Bad verb ose violates referential transparency

defun isatest x y n

catch isa isatest x y n

defun isatest x y n

cond eq x y t

member y get x isa throw isa t

zerop n nil

t any mapcar

lambda xx

isatest xx y n

get x isa

Problems

catchthrow is gratuitous

member test mayormay not b e helping

mapcar generates garbage

any tests to o late

throw tries to x this

resultisthat any never gets called

Control Abstraction

Keep It Simple

Some recommendations for use of catch and throw

Use catch and throw as subprimitives when imple

menting more abstract control structures as macros

but do not use them in normal co de

Sometimes when you establish a catch programs

may need to test for its presence In that case

restarts maybemore appropriate

Control Abstraction

Keep It Simple

Good

defun isatest sub super maxdepth

Test if SUB is linked to SUPER by a chain of ISA

links shorter than maxdepth

and maxdepth

or eq sub super

some lambda parent

isatest parent super

maxdepth

get sub isa

Also good uses to ols

defun isatest sub super maxdepth

depthfirstsearch start sub goal is super

successors getisa

maxdepth maxdepth

Write clearlydont b e to o clever

Kernighan Plauger

Be Aware

Do es improving something change the semantics

Do es that matter

Control Abstraction

Avoid Complicated Lamb da Expressions

When a higherorder function would need a compli

cated lamb da expression consider alternatives

dolist or loop

generate an intermediate garbage sequence

Series

Macros or read macros

lo cal function

Sp ecic makes it clear where function is used

Do esnt clutter up global name space

Lo cal variables neednt b e arguments

BUT some debugging to ols wont work

Control Abstraction

Avoid Complicated Lamb da Expressions

Find the sum of the squares of the o dd numb ers in a

list of integers

All Go o d

reduce numbers

key lambda x if oddp x x x

flet squareodd x if oddp x x x

reduce numbers key squareodd

loop for x in list

when oddp x sum x x

collectsum chooseif oddp numbers

Also consider maybeappropriate sometimes

Introduce read macro

reduce numbers key Lif oddp

Generate intermediate garbage

reduce remove evenp mapcar square numbers

Control Abstraction

Functional vs Imp erative Style

It has b een argued that imp erative style programs are

harder to reason ab out Here is a bug that stems from

an imp erative approach

Task Write a version of the builtin function find

Bad incorrect

defun ifind item seq key test eql testnot nil

start sflag end nil

key identity fromend nil

if sflag setq seq subseq seq start

if end setq seq subseq seq end

Problems

Taking subsequences generates garbage

No appreciation of listvector dierences

Error if b oth start and end are given

Error stems from the up date to seq

Control Abstraction

Example Simplication

Task a simplier for logical expressions

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 simpaux and cdr pred

eq car pred or

cons or simpaux or cdr pred

t pred

defun simpaux op preds

cond null preds nil

and listp car preds

eq caar preds op

append simpaux op cdar preds

simpaux op cdr preds

t cons simp car preds

simpaux op cdr preds

Control Abstraction

A Program to Simplify Expressions

Problems

No meaningful name for simpaux

No reusable parts

No data accessors

and and a not simplied

Better usable to ols

defun simpbool exp

Simplify a boolean andor expression

cond atom exp exp

member op exp and or

maybeadd op exp

collectargs

op exp

mapcar simpbool args exp

t exp

defun collectargs op args

Return the list of args splicing in args

that have the given operator op Useful for

simplifying exps with associate operators

loop for arg in args

when startswith arg op

nconc collectargs op args arg

else collect arg

Control Abstraction

Build Reusable Tools

defun startswith list element

Is this a list that starts with the given element

and consp list

eql first list element

defun maybeadd op args optional

default getidentity op

If arg return it if return the default

If there is more than arg cons op on them

Example maybeadd progn f x f x

Example maybeadd

Example maybeadd

assuming is defined as the identity for

cond null args default

length args first args

t cons op args

deftable identity

init and t or nil progn nil

Syntactic Abstraction

A Language for Simplifying

Task A Simplier for all Expressions

simplify x y y x

simplify if f x nil

simplify and a and and b and a b

Syntactic abstraction denes a new language that is

appropriate to the problem

This is a problemoriented as opp osed to co deoriented

approach

Dene a language for simplication rules then write

some

definesimplifier expsimplifier

x x

x x

x x

x x

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

Syntactic Abstraction

Design Your Language Carefully

The ability to change notations emp owers human

b eings Scott Kim

Bad verb ose brittle

setq timesrule

simplify

e

timesrule

setq rules list timesrule

Insucient abstraction

Requires naming timesrule three times

Intro duces unneeded global variables

Unconventional indentation

Sometimes it is useful to name rules

defrule timesrule

x

Although I wouldnt recommend it in this case

Syntactic Abstraction

An Interpreter for Simplifying

Now write an interpreter or a compiler

defun simplify exp

Simplify expression by first simplifying components

if atom exp

exp

simplifyexp mapcar simplify exp

defunmemo simplifyexp exp

Simplify expression using a rule or math

The expression is nonatomic

rulebasedtranslator exp simplificationrules

rulepattern first

ruleresponse third

action simplify

otherwise evalexp

This solution is go o d b ecause

Simplication rules are easy to write

Control ow is abstracted away mostly

It is easy to verify the rules are correct

The program can quickly b e up and running

If the approach is sucient were done

If the approach is insucient weve saved time

If it is just slow we can improve the to ols

and other uses of the to ols will b enet to o

Syntactic Abstraction

An Interpreter for Translating

Success comes from doing the same thing over and

over again each time you learn a little bit and you do

a little b etter the next time Jonathan Sachs

Abstract out the rulebased translator

defun rulebasedtranslator

input rules key matcher patmatch

rulepattern first ruleresponse rest

action identity sub sublis

otherwise identity

Find the first rule that matches input and apply the

action to the result of substituting the match result

into the rules response If no rule matches apply

otherwise to the input

loop for rule in rules

for result funcall matcher

funcall rulepattern rule input

when not eq result fail

do RETURN funcall action

funcall sub result

funcall ruleresponse rule

finally RETURN funcall otherwise input

If this implementation is to o slow we can index b etter

or compile

Sometimes reuse is at an informal level seeing how

the general to ol is built allows a programmer to con

struct a custom to ol with cut and paste

Syntactic Abstraction

Saving duplicate work defunmemo

Less extreme than dening a whole new language is to

augment the Lisp language with new macros

defunmemo makes a function rememb er all computa

tions it has made It do es this by maintaining a hash

table of inputoutput pairs If the rst argument is just

the function name of things happ en If there

is exactly arg and it is not a rest arg it makes a

eql table on that arg Otherwise it mak es an equal

table on the whole arglist

You can also replace fnname with name test size

keyexp This makes a table with given test

and size indexed by keyexp The hash table can be

cleared with the clearmemo function

Examples

defunmemo f x eql table keyed on x

complexcomputation x

defunmemo f test eq x eq table keyed on x

complexcomputation x

defunmemo g x y z equal table

anothercomputation x y z keyed on on x y z

defunmemo h keyexp x x optional debug

eql table keyed on x

Syntactic Abstraction

Saving Duplicate Work defunmemo

defmacro defunmemo fnnameandoptions rest args

body body

Documentation string on previous page

let vars arglistvars args

flet genbody fnname key test equal

size keyexp

evalwhen load eval compile

setf get fnname memoizetable

makehashtable test test

when size size size

defun fnname args

gethashorsetdefault

keyexp

get fnname memoizetable

progn body

Body of the macro

cond consp fnnameandoptions

Use usersupplied keywords if any

apply genbody fnnameandoptions

and length vars

not member rest args

Use eql table if it seems reasonable

genbody fnnameandoptions test eql

keyexp first vars

t Otherwise use equal table on all args

genbody fnnameandoptions test equal

keyexp list vars

Syntactic Abstraction

More Macros

defmacro withgensyms symbols body

Replace the given symbols with gensymed versions

everywhere in body Useful for macros

Does this everywhere not just for variables

sublis mapcar lambda sym

cons sym gensym string sym

symbols

body

defmacro gethashorsetdefault key table default

Get the value from table or set it to the default

Doesnt evaluate the default unless needed

withgensyms keyvar tabvar val foundp

let keyvar key

tabvar table

multiplevaluebind val foundp

gethash keyvar tabvar

if foundp

val

setf gethash keyvar tabvar

default

Syntactic Abstraction

Use Macros Appropriately

See tutorial by Allan Wechsler

The design of macros

Decide if a macro is really necessary

Pick a clear consistent syntax for the macro

Figure out the right expansion

Use defmacro and to implement the mapping

In most cases also provide a functional interface

useful sometimes easier to alter and continue

Things to think ab out

Dont use a macro where a function would suce

Make sure nothing is done at expansion time mostly

Evaluate args lefttoright once each if at all

Dont clash with user names withgensyms

Syntactic Abstraction

Problems with Macros

Bad should b e an inline function

defmacro namepartof rule

car rule

Bad should b e a function

defmacro defpredfun name evaluationfunction

push makepredfun name name

evaluationfunction evaluationfunction

predicatefunctions

Bad works at expansion time

defmacro defclass name rest def

setf get name class def

list quote name

Syntactic Abstraction

Problems with Macros

Bad Macros should not eval args

defmacro addperson name mother father sex

unevaluatedage

let age eval unevaluatedage

list if age

addperson bob joanne jim male computeage

What if you compiled this call now and loaded it in a

few years

Better Let the compiler constantfold

declaim inline computeage

defmacro addperson name mother father sex age

funcall if age

Very Bad what if increment is n

defmacro for variable start end optional increment

body body

if not numberp increment setf increment

for i

Syntactic Abstraction

Macros for Control Structures

Good lls a hole in orthogonalityofCL

defmacro dovector var vector key start end

body body

Do body with var bound to each element of vector

You can specify a subrange of the vector

block nil

mapvector lambda var body

vector start start end end

defun mapvector fn vector key start end

Call fn on each element of vector within a range

loop for i from start below or end length vector

do funcall fn aref vectorvar index

Iterates over a common data typ e

Follows established syntax dolist dotimes

Ob eys declarations returns

Extends established syntax with keywords

One bad p oint

No result as in dolist dotimes

Syntactic Abstraction

Help er Functions For Macros

Most macros should expand into a call to a function

The real work of the macro dovector is done by a func

tion mapvector b ecause

Its easier to patch

Its separately callable useful forprogram

The resulting co de is smaller

If prefered the help er can b e made inline

Often go o d to avoid consing closures

dovector x vect print x

macroexpands to

block nil

mapvector 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

Syntactic Abstraction

Setf Metho ds

As in macros we need to b e sure to evaluate each form

exactly once in lefttoright order

Make sure macro expansions macroexpand getsetfmethod

are done in the right environment

defmacro deletef item sequence rest keys

environment environment

Destructively delete item from sequence

multiplevaluebind temps vals stores storeform

accessform

getsetfmethod sequence environment

assert length stores

let itemvar gensym ITEM

let itemvar item

mapcar list temps vals

first stores

delete itemvar accessform keys

storeform

Programming in the Large

Programming in the Large

Be aware of stages of software development

Gathering requirements

Architecture

Comp onent Design

Implementation

Debugging

Tuning

These can overlap The p oint of exploratory program

ming is to minimize comp onent design time getting

quickly to implementation in order to decide if the ar

chitecture and requirements are right

Knowhow to put together a large program

Using packages

Using defsystem

Separating source co de into les

Do cumentation in the large

Portability

Error handling

Interfacing with nonLisp programs

Programming in the Large

Separating Source Co de into Files

The following factors aect how co de is decomp osed

into les

Languageimp osed dep endencies

macros inline functions CLOS classes b efore use

Stratied design

isolate reusable comp onents

Functional decomp osition

group related comp onents

Compatibility with to ols

chose go o d size les foreditor compilefile

Separate OSmachinevendorsp ecic implemen

tations

Programming in the Large

Using Comments Eectively

Use comments tofor

Explain philosophy Dont just do cument de

tails also do cument philosophy motivation and

metaphors that provide a framework for under

standing the overall structure of the co de

Oer examples Sometimes an example is worth

a pile of do cumentation

Have conversations with other develop ers In

a collab orative project you can sometimes ask a

question just by putting it in the source You may

come back to nd it answered Leave the question

and the answer for others who might later wonder

to o

Maintain your to do list Put a sp ecial marker

on comments that you want to return to later

or mayb e use for higher priority Some

projects keep to do lists and change logs in les

that are separate from the source co de

defun factorial n

What about negative numbers Joe Aug

And what about nonnumbers Bill Aug

if n

n factorial n

Programming in the Large

Do cumentation Say What You Mean

Q Do you ever use comments when you write co de

Rarely except at the b eginning of pro cedures and

then I only comment on the data structure I dont

comments on the co de itself b ecause I feel that prop

erly written co de is very selfdo cumented Gary

Kildall

I gure there are twotyp es of comments oneisex

plaining the obvious and those are worse than worth

less the other kind is when you explain really involved

convoluted co de Well I always try to avoid convo

luted co de I try to program really strong clear clean

co de even if it makes an extra ve lines I am almost

of the opinion that the more comments you need the

worse your program is and something is wrong with it

Wayne Ratli

Dont comment bad co derewrite it Kernighan

Plauger

Describ e the purp ose and structure of system

Describ e each le

Describ e each package

Do cumentation strings for all functions

Consider automatic to ols manual

Make co de not comments

Programming in the Large

Do cumentation Overcommenting

These lines must do cument a major 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 on of 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 of all nodes dominate d by the node

It returns the node set

implemen ta ti on Stores the nodes which have already been describe d

in descri be n od es

Before tracing the descript io n of a node it

checks whether the node was already been describe d

to avoid describ in g the same node repeatedly

The variable descri be no de s is updated by des

sideeff ec ts Prints the node s descripti on s

written CCC

modified CCC

ejm

njm

njm

Programming in the Large

Do cumentation Overcommenting

defmacro describe rest snepsulexp

let crntct processcontextdescr snepsulexp

ns incontextns nseval getsndescr

snepsulexp

crntct

describednodes newns

full nil

declare special crntct describednodes full

terpri

mapc lambda n

if not ismembns n describednodes

PPnodetree des n

ns

terpri

values ns crntct

Problems

Do cumentation to o long lose big picture

Do cumentation is wrong describ edno des

Do cumentation is ineective no do c string

Do cumentation is redundant arglist

Bad idea to shadow Lisps describ e function

Need function that is separate from macro

Abbreviations are obscure

Programming in the Large

Do cumentation Commenting

Better

This do esnt handle crntct whatever that is

defmacro desc rest snepsulexp

Describe the node referred to by this expression

This macro is intended as an interactive debugging tool

use the function describenodeset from a program

describenodeset expnodeset snepsulexp

defun describenodeset nodeset

Print all the nodes in this node set

Accumulate describednodes to weed out duplicates

let describednodes newnodeset

terpri

dolist node nodeset

unless ismembernodeset node describednodes

des adds nodes to describednodes

ppnodetree des node describednodes

terpri

nodeset

Programming in the Large

Portability

Makeyour program run well in the environments you

use

But be aware that you or someone else may want to

use it in another environment someday

Use feature and feature

Isolate implementationdep endent parts

Maintain one source and multiplebinaries

Evolve towards dpANS CL

Implement missing features if needed

Be aware of vendorsp ecic extensions

Programming in the Large

Foreign Function Interface

Large programs often have to interface with other pro

grams written in other languages Unfortunately there

is no standard for this

Learn your vendors foreign interface

Try to minimize exchange of data

Beware of areas that cause problems

Memory management

Signal handling

Miscellaneous

Mean what you say

Dont mislead the reader

Anticipate readers misunderstandings

Use the right level of sp ecicity

Be careful with declarations

Incorrect declarations can break co de

Onetoone corresp ondence

Bad declaration only madeup example

defun lookup name

declare type string name

if null name

nil

or gethash name symboltable

makesymbolentry name

Should b e declare type or string null name

Miscellaneous

Naming Conventions Be Consistent

Be consistent in names

Be consistent with capitalization

most prefer likethisnot LikeThis

specialvariable

constant or some convention

Dylan uses class

Consider structureslot

p or or n or to

verbobject deletefile

objectattribute integerlength

compare namefile and filename

dont use objectverb or attributeobject

Order arguments consistently

Distinguish internal and external functions

Dont mix optional and keyusecarefully

or optional args Dylan

Use keywords consistently key test end

Miscellaneous

Naming Conventions Cho ose Names Wisely

Cho ose Names wisely

Minimize abbreviations

Most words have many p ossible abbreviations but

only one correct sp elling Sp ell out names so they

are easier to read rememb er and nd

Some p ossible exceptions char demo intro and

paren These words are b ecoming almost likereal

words in English A go o d test for native English

sp eakers is Would you say the word aloud in

conversation Our earlier example with crntct and

processcontextdescr wouldnt pass this test

Dont shadow a lo cal variable with another

Clearly showvariables that are up dated

Avoid ambiguous names Use previous or final

instead of last

Miscellaneous

Notational Tricks Parens in Column

Most text editors treat a left paren in column as the

start of a toplevel expression Aparen inside a string

in column may confuse the editor unless you provide

a backslash

defun factorial n

Compute the factorial of an integer

dont worry about noninteger args

if n

n factorial n

Many text editors will treat a def in column as a

denition but not a def in other columns So you

mayneedtodothis

progn

defun foo

defun bar

Miscellaneous

MultiLine Strings

In case of a multiline string as a literal constant such

as

defun findsubjectline messageheaderstring

search

Subject messageheaderstring

consider instead using readtime evaluation and a call

to format

defun findsubjectline messageheaderstring

search format nil Subject messageheaderstring

Where the same string is used many times consider

using a global variable or named constant

defparameter subjectmarker format nil Subject

defun findsubjectline messageheaderstring

search subjectmarker messageheaderstring

Miscellaneous

MultiLine Strings contd

Forlongformat strings you can indent the continua

tion lines with Return or Return The following

twoforms do the same thing

format t This is a long string

This is more of that string

This is a long string

This is more of that string

format t This is a long string

This is more of that string

This is a long string

This is more of that string

The latter syntax p ermits you to indent a xed amount

easily

format t This is a long string

This is more of that string indented by one

This is a long string

This is more of that string indented by one

Miscellaneous

Notational Tricks MultiLine Comments

Avoid using and in strings since it will confuse any

later attempt to comment out such a string Again a

backslash helps

Good

defun begincomment writestring

defun endcomment writestring

This means that you can later comment out sections

containing these strings without editing the strings them

selves

If your editor provides supp ort commentregion and

uncommentregion commands it is b etter to use ex

plicit comments That way the reader will never get

confused ab out which sections have b een commented

out

Miscellaneous

Some Red Flags

The following situations are red ags They are of

ten symptoms of problemseven though technically

most of them do happ en in completely legitimate sit

uations as well If you see one of these red ags you

do not automaticallyhavea problem in your co de but

you should still pro ceed cautiously

Any use of eval

Any use of gentemp

Any use of append

The absence of an environment parameter in a

macro that uses setf orcallsmacroexpand

Writing a condition handler fortyp e error

including use of ignoreerrors

Any use of the cr functions except caar cadr

where the is all ds

Noknown go o d uses

Miscellaneous

Avoid Common Mistakes

Good style involves avoiding mistakes

Always prompt for input

Or user wont know whats happ ening

Understand defvar and defparameter

Understand flet and labels

Understand multiple values

Understand macros shown ab ove

Recompile after changing macros or

inline functions

Use lambda not lambda

Rememb er f is just function f

Use test equal as needed

Make sure declarations are eective

Have a p olicy for destructive functions

Miscellaneous

Destructive Functions

Have a p olicy for destructive functions

Most programs use destructive up dates when they

can prove the arguments are not needed elsewhere

as when a function nconcs partial results

Otherwise assume that arguments cannot be al

tered

Assume that results will not b e altered

Major interfaces often make copies of results they

pass out just to b e safe

Note that generation scavenging GC can b e slowed

down by destructive up dates

Miscellaneous

Minor Mistakes

Bad

defun combineindeplambdas arcexp

apply

mapcar evalarcexp cdr arcexp

apply may exceed callargumentslimit

map car generates garbage

cdr violates data abstraction

Good

reduce inarcs arcexp key evalarcexp

Learn to use accumulators

defun product numbers optional key identity

accum

Like reduce numbers but bails out early

when a zero is found

if null numbers

accum

let term funcall key first numbers

if term

product rest numbers key accum term

Consider Series

collectfn number constantly numbers

Miscellaneous

MultiTasking and MultiPro cessing

MultiTasking Time Slicing

It is reasonable to sp end time structuring your co de

to work well in the face of multitasking Many com

mercial Lisp implementations have this even though

there is not yet a p ortable standard It ts in well with

existing language semantics

Watch out for global state like setq and prop erty

lists

Synchronize pro cesses with withoutinterrupts

withoutaborts withoutpreemption etc Consult

implementationsp ecic do cumentation for the set

of available op erators and learn how they dier

MultiPro cessing True Parallelism

Think ab out true parallelismbutdontwaste a lot of

time structuring your programs to work well if things

suddenly b ecome parallelized Making a sequential pro

gram into a parallel one is a nontrivial change that

wont happ en by accident eg due to some overnight

change in Common Lisps semantics It will take a

whole new language to supp ort this youll have time

to prepare

Miscellaneous

Exp ect The Unexp ected

Murphys Law

If something can go wrong it will

Dont omit checking for things b ecause youre sure

something will never happ en unless youre very sure

And even then dont omit them anyway It is su

ciently commonplace to get errors from systems saying

This cant happ en that its clear that p eople are not

always as brilliant as they think

Miscellaneous

Read Other Peoples Co de

You need to study other p eoples work Their ap

proaches to problem solving and the to ols they use

give you a fresh way to lo ok at your own work

Gary Kildall

Ive learned a lot from lo oking at other p eoples pro

grams Jonathan Sachs

I still think that one of the nest tests of programming

abilityis to hand the programmer ab out pages of

co de and see how quickly he can read through and

understand it Bill Gates

The b est wayto prepare to b e aprogrammeris to

write programs and to study great programs that other

p eople have written In my case I went to the garbage

cans at the Center and I shed out

listings of their op erating system Bill Gates

Youve got to b e willing to read other p eoples co de

then write your own then have other people review

your co de Bill Gates

Lisp Machine Op erating System

Internet FTP sites complanglisp FAQ

CMU CL Compiler and Utilities

examples

Miscellaneous

Example deftable

Task Make it easy to dene and use tables

Like defstruct

Should b e fast inline functions

Should handle one or multiple tables

CLOS

Op erations Arguments and return values

Default values Mutated or returned

Separation b etween user and implementor co de with

supp ort for b oth

Way to dene new table implementations

Naming packages

Do cumented limitations

Instrumentation

Automatic selection

Lessons learned

Capture common abstractions tables others

Complex macros can b e designed with a little care

Consider the p ossibility of extension

Miscellaneous

Prototyp e

Lisp allows you to develop prototyp es easily

Plan to throw one away you will anyhow Fred

Bro oks

I think a lot b efore I do anything and once I do some

thing Im not afraid to throwitaway Its very imp or

tant that a programmer b e able to lo ok back at a piece

of co de like a bad chapter in a b o ok and scrap it with

out lo oking back John Warno ck

Dont bind early dont ever make decisions earlier

than you have to Stay an order of magnitude more

general than you think you need b ecause you will end

up needing it in the long term Get something working

very quickly and then b e able to throwitaway John

Warno ck

So I tend to write a few lines at a time and try it out

get it to work then write a few more lines I try to

do the least amount of work p er iteration to makereal

substantive change Wayne Ratli

b egan with a working program and it continued

to b e a working program throughout its development

Jonathan Sachs

Miscellaneous

Other Ideas

Learn to typ e If you typ e less than wpm youre

holding yourself back

Also while youre working hard on a complicated pro

gram its imp ortant to exercise The lack of physical

exercise do es most programmers in It causes a loss of

mental acuity John Page

Q What do es it take to b ecome a great programmer

Whatdoesittake to b e go o d at anything What do es

it take to b e a go o d writer Someone whos go o d is a

combination of twofactors an accidental mental cor

resp ondence to the needs of the disciplines combined

with a mental abilityto not be stupid Thats a rare

combination but its not at all mystical A good pro

grammer must enjoy programming and be interested

in it so he will try to learn more Agoodprogrammer

also needs an aesthetic sense combined with a guilt

complex and a keen awareness of when to violate that

aesthetic sense The guilt complex forces him to work

harder to improve the program and to bring it more in

line with the aesthetic sense Bob Frankston

Miscellaneous

Recommended Bo oks

Intro ductions to Common Lisp

Rob ert Wilensky Common LISPcraft

Deb orah G Tatar A Programmers Guide to Com

mon Lisp

Ro dney A Bro oks Programming in Common Lisp

References and a MustHave

Guy L Steele Common Lisp The Language nd

Edition

ANSI Draft Prop osed Common Lisp Standard

Harold Ab elson and with Julie

Sussman Structure and Interpretation of Com

puter Programs Scheme

Miscellaneous

Recommended Bo oks

More Advanced

Patrick H Winston and Berthold K PHorn LISP

rd edition

Wade L Hennessey Common Lisp

Sonya E Keene ObjectOriented Programming in

Common Lisp A Programmers Guide to CLOS

Eugene Charniak Christopher K Riesb eck Drew

V McDermott and James R Meehan Articial

Intelligence Programming nd edition

Peter Norvig Paradigms of AI Programming Case

Studies in Common Lisp

Perio dicals

LISP Pointers ACM SIGPLAN Since

LISP and Symb olic Computation Since

Pro ceedings of the biannual ACM Lisp and Func

tional Programming Conference Since

Miscellaneous

Quotes

Quotes from Programmers at Work Susan Lammers

Microsoft Press

Bob Frankston Software Arts VisiCalc Lotus

Bill Gates Altair BASIC Microsoft

Gary Kildall Digital Research CPM

Scott Kim Stanford Xerox Inversions

Butler Lampson Xerox Ethernet Alto Dorado

Star Mesa DEC

John Page HP Software Publishing PFSFILE

Wayne Ratli NASA AshtonTate dBASE I I

Jonathan Sachs MIT Lotus

Charles Simonyi Xerox Bravo Microsoft Word

Excel

John Warno ck NASA Xerox Adob e PostScript

Miscellaneous

Quotes

Other quotes

Harold Ab elson MIT SICP Logo

Judy Anderson Harlequin Inc

Fred Bro oks IBM architect nowatUNC

BearBryant Alabama fo otball coach

Brian Kernighan PJ Plauger Bell Labs UNIX

David McDonald MIT UMass natural language

generation

Guy Steele Thinking Machines Scheme CLtL

Gerald Sussman MIT SICP Scheme

Deb orah Tatar DEC Xerox author

Niklaus Wirth ETH Zurich Pascal

Almost all Bad Co de examples are taken from published

b o oks and articles whose authors should know b etter

but will remain anonymous