STYLE: Make this document cover multiple languages.
[sod] / STYLE
CommitLineData
cbed66ad 1Notes on coding style
1528431b 2
cbed66ad
MW
3* General
4
5** Layout
6
7Lines are 77 characters at most, except for strange special effects.
8Don't ask. This is not negotiable, though. Don't try to tell me that
9your monitor is very wide so you can read longer lines. My monitor is
10likely at least as wide. On the other hand, most lines are easily short
11enough to fit in my narrow columns, so the right hand side of a wide
12window would be mostly blank. This seems wasteful to me, when I could
13fill that space with more code.
14
15Horizontal whitespace for layout purposes -- i.e., indentation and
16alignment, rather than just separating words -- consists of as many tabs
17as possible, followed by as many spaces as necessary to reach the target
18column. Tab stops occur at every eight columns. You can tell this
19because when you cat a file to your terminal, that's how the tabs
20appear. Editors which disagree about this are simply wrong.
21
22My indentation quantum is usually two columns. It seems that some
23modern editors are deeply confused, and think that tab width and
24indentation quantum are the same thing, but they aren't. Such broken
25editors will make a hopeless mess of my code. If you have the
26misfortune to use such an editor, maybe you could contribute patches to
27fix it.
28
29
30* Lisp style
31
32** Language subset and extensions
1528431b
MW
33
34None of ANSI Common Lisp is off-limits.
35
828cb3b1
MW
36I think my Lisp style is rather more imperative in flavour than most
37modern Lisp programmers. It's probably closer to historical Lisp
a1b51e19
MW
38practice in that regard, even though I wasn't writing Lisp back then. A
39lot of this is because I don't assume that the Lisp implementation
40handles tail calls properly: Common Lisp is not Scheme.
828cb3b1 41
1528431b
MW
42I make extensive use of CLOS, and macros. On a couple of occasions I've
43made macros which use CLOS generic function dispatch to compute their
44expansions. The parser language is probably the best example of this in
828cb3b1
MW
45the codebase.
46
a1b51e19
MW
47I like hairy ~format~ strings. I've intentionally opted to leave them
48as challenges to the reader rather than explain them.
1528431b
MW
49
50I've avoided hairy ~loop~ for the most part, not because I dislike it
51strongly but because others do and I don't find that it wins big enough
52for the fight to be worthwhile.
53
54I only use ~&aux~ lambda-list parameters in ~defstruct~ BOA
55constructors, for special effects.
56
57I use ~car~, not ~first~, and ~cdr~, not ~rest~. Similarly, I use
58~cadr~, not ~second~, and I'm not afraid to use ~cddr~ or ~cadar~.
59
60Similarly, I've not used ~elt~, preferring to know what kind of sequence
61I'm dealing with, or using the built-in sequence functions.
62
63I'm happy to use ~1+~, and I like the brevity of ~1-~ enough to use it
64despite its terrible name.
65
66There are no reader syntax extensions in the code. This is because I
67couldn't think of any way they'd be especially helpful, and not because
68I'm in any way opposed to them.
69
70The main translator, in the ~SOD~ package, tries to assume very little
71beyond ANSI Common Lisp and what's included in just about every serious
72implementation: specifically, MOP introspection, and Gray streams.
73There's intentionally no MOP intercession.
74
7e55d099
MW
75The frontend additionally makes use of ~cl-launch~, but the dependency
76is actually quite weak, and it could be replaced with a different, maybe
1528431b
MW
77implementation-specific, mechanism fairly easily. I'm keen to take
78patches which improve frontend portability.
79
80I'm more tolerant of extensions and external dependencies in the test
81suite, which makes additional use of ~xlunit~. Running the test suite
82isn't essential to getting the translator built, so this isn't as much
83of a problem.
84
cbed66ad 85** Layout
1528431b
MW
86
87I pretty much let Emacs indent my code for me, based on information
88collected by SLIME. Some exceptions:
89
90 + DSLs (e.g., the parser language) have their own space of macros
91 which Emacs doesn't understand and for the most part I haven't
92 bothered to teach it.
93
94 + Emacs sometimes does a bad job with hairy ~loop~ and requires manual
95 fixing. Since I don't use hairy ~loop~ much, this isn't a major
96 problem.
97
f458e64e
MW
98 + Emacs indents lambda lists really badly. I often prefer to put the
99 entire lambda list on its own line than to split it. If I have to
100 split a simple lambda list, without lambda-list keywords, I just
101 align the start of each subsequent line with the start of the first
102 argument. I break hairy lambda lists before lambda-list keywords,
103 and the start of a subsequent line aligns with the first argument
104 name following the lambda-list keyword which begins the group, so
105 that the lambda-list keyword stands out.
106
107 : (defun many-arguments (first second third
108 : fourth fifth)
109 : ...)
110
111 : (defun hairy-arguments (first second third
112 : &optional fourth fifth
113 : sixth
114 : &rest others)
115 : ...)
116
117 I don't know what I'd do if I had a hairy lambda list with so many
118 mandatory positional arguments that I had to split them. So far,
119 this situation hasn't come up.
120
1528431b
MW
121Lisp code does have a tendency to march across to the right quite
122rapidly given a chance. I have a number of strategies for dealing with
123this.
124
125 + Break a long nested calculation into pieces, giving names to the
126 intermediate results, in a ~let*~ form.
127
7e55d099
MW
128 + Hoist deeply nested complex computations out into ~flet~ or
129 ~labels~, and then invoke them from inside whatever complicated
1528431b
MW
130 conditional mess was needed to decide what to do.
131
132 + Shrug my shoulders and let code dribble down the right hand side for
133 a bit.
134
cbed66ad 135** Packages and exporting
1528431b
MW
136
137A package collects symbols which are given meanings in one or more
138source files. If a package's code is all in one file, then the package
139definition can be put in that file too; otherwise I put it in its own
140file.
141
142I don't put ~:export~ in package definitions. Instead, I scatter calls
143to the ~export~ function throughout the code, right next to where the
144relevant symbol is defined. This has three important advantages.
145
146 + You can tell, when you're reading the code which defines ~foo~,
147 whether ~foo~ is exported and therefore a defined part of the
148 package interface.
149
150 + When you know that you're writing a thing which will form part of
151 the package interface, you don't have to go off and edit some other
152 file to export it.
153
154 + A master list of exported symbols becomes a merge hazard: if two
155 different branches add symbols to nearby pieces of the master list
156 then you get a merge conflict for no especially good reason.
157
158There's an apparent disadvantage: there's no immediately visible master
159list of exported symbols. But that's not a big problem:
160
161: (loop for s being the external-symbols of pkg collect s)
162
163See ~doc/list-symbols.lisp~ for more sophisticated reporting. (In
164particular, this identifies what kind of thing(s) each external symbol
165names.)
166
cbed66ad 167** Comments and file structuring
1528431b
MW
168
169A file starts with a big ~;;;~ comment bearing the Emacs ~-*-lisp-*-~
170marker, a quick description, and copyright and licensing boilerplate. I
171don't use four-semicolon comments, and I only use ~#|~ ... ~|#~ for
172special effects.
173
174Then there's package stuff. There may be a ~cl:defpackage~ form (with
175explicit package qualifier) if the relevant package doesn't have its own
a1b51e19
MW
176package definition file. I use gensyms to name packages: strings don't
177seem right, and symbols would leak into some unrelated package.
1528431b
MW
178
179Then there's ~cl:in-package~. Like ~defpackage~, I use a gensym to name
180the package. I can't think offhand of a good reason to have a file with
7e55d099
MW
181sections `in' more than one package. So, the ~in-package~ form goes at
182the top of the file, before the first section header. If sections are
183going to end up in separate packages, I think I'd put a ~cl:in-package~
184at the top of each section in case I wanted to reorder them.
1528431b
MW
185
186The rest of the file consists of Lisp code. I don't use page boundaries
187~^L~ to split files up. Instead, I use big banner comments for this:
188
189: ;;;--------------------------------------------------------------------------
190: ;;; Section title.
191
192Sections don't usually have internal comments, but if they did they'd
193also be ~;;;~ comments.
194
195Almost all definitions get documentation strings. I've tried to be
196consistent about formatting.
197
198 + Docstring lines are 77 characters or less.
199
200 + The first line gives a summary of what the thing does. The summary,
201 together with the SLIME-generated synopsis, is likely enough to
202 remind you what the thing does.
203
204 + The rest of the lines are indented by three spaces, and explain
205 carefully what the thing does and what all the parameters mean.
206
207Smallish functions and macros don't usually need any further
208commentary. Big functions often need to be split into bitesize pieces
209with their own internal ~;;~ comments. The idea is that these comments
210should explain the code's overall strategy to the reader, and help them
211figure out how a piece fits into that strategy.
212
213Winged, single ~;~ comments are very rare.
214
215Files end, as a result of long tradition, with a comment
216
217: ;;;----- That's all, folks --------------------------------------------------
218
cbed66ad 219** Macro style
1528431b
MW
220
221I don't mind complicated macros if they're doing something worthwhile.
222They need to have good documentation strings, though.
223
224That said, where possible I've tried to factor macros into an actual
225macro providing the syntactic sugar, and a function which receives the
226parameters and $\eta$-expanded forms, and does the actual work.
227
228It's extremely bad taste for a macro to evaluate its evaluable
229parameters in any order other than strictly left to right, or to
230evaluate them more than once.
231
cbed66ad 232** Data structures
1528431b
MW
233
234I've tended to be happy with plain lists for homogeneous-ish
235collections. Strongly heterogeneous collections (other than input
236syntax, destructured using ~defmacro~ or ~destructuring-bind~) I've
237tended to make a proper data type for.
238
239My first instinct when defining a new structure is to use ~defclass~.
240While it's annoyingly verbose, it has the immense benefit over
241~defstruct~ that it's safe to redefine CLOS classes in a running image
242without the world breaking, and I usually find it necessary to add or
243change slots while I'm working on new code. Once a piece of code has
244settled down and I have a good feel for what my structure is actually
245doing, I might switch the ~defclass~ for a ~defstruct~. Several
246questions influence my decision.
247
248 + Do slot accesses need to be really fast? My usual Lisp
249 implementations aggressively optimize ~defstruct~ accessor
250 functions.
251
7e55d099 252 + Have I subclassed my class? While I can move over a
1528431b
MW
253 single-inheritance tree using ~:include~, it seems wrong to do this
254 most of the time. Also, I'd be precluding subclasses from multiple
255 inheritance, and I'd either have to prohibit subclassing by
256 extensions or have to commit to ~defstruct~ in the documentation.
257 In general, I'm much happier committing to ~defclass~.
258
259 + Are there methods specialized on my class? Again, structure classes
260 make fine method specializers, but it doesn't seem right.
261
262Apart from being hard to redefine, ~defstruct~ does a pretty good job of
263making a new structure type. I tend to tidy up a few rough edges.
264
265 + The default predicate always has ~-p~ appended. If the class name
266 is a single word, then I'll explicitly name the predicate with a
267 simple ~p~ suffix. For example, ~ship~ would have the predicate
a51bf71a 268 ~shipp~, rather than ~ship-p~.
1528431b
MW
269
270 + If there are slots I can't default then I'll usually provide a BOA
271 constructor which sets them from required parameters; other slots
272 I'll set from optional or keyword parameters according to my taste
273 and judgement.
274
275 + Slots mustn't be given names which are external in any package.
276 Unfortunately, slot names are used in constructing accessor names,
277 and sometimes the right accessor name involves a prohibited symbol.
278 I've mostly addressed this by naming the slot ~%foo~, and then
279 providing inline reader and writer functions. (CLOS class
280 definitions don't have this problem because you get to set the
281 accessor function names independently of the slot names.)
282
283 + BOA constructors are strange. You can set the initial slots based
284 on an arbitrary computation on the provided parameters, but you have
285 to roll up your sleeves and mess with ~&aux~ parameters to pull it
286 off.
287
cbed66ad 288** Naming
1528431b
MW
289
290I'm a traditionalist in some ways, and one of the reasons I like Lisp is
291the richness of its history and tradition.
292
293In other languages, I tend to use single- or two-letter names for
294variables and structure slots; not so much in Lisp. Other languages
295express more using punctuation, so the names stand out easily; I find
296that short names can be lost more easily in Lisp.
297
298I've also tended to go for fairly prosaic names, taking my inspiration
299from the CLOS MOP. While I mourn the loss of whimsical names like
300~haulong~ and ~haipart~, I've tried to avoid inventing more of them.
301
f458e64e
MW
302There's a convention, which I think comes from ML, of using ~_~ where a
303binding occurrence of a variable name is expected, to signify that that
304the corresponding value is to be discarded. Common Lisp, alas, doesn't
305have such a convention. Instead, there's a sequence of silly names used
306with the same intention, and the bindings are then explicitly ignored
307with a declaration. The names begin ~hunoz~, ~hukairz~, and (I think)
308~huaskt~.
1528431b 309
cbed66ad 310** Declarations
1528431b
MW
311
312The code is light on declarations, other than ~ignore~ and similar used
313to muffle warnings. The macros try to do sensible things with
314declarations, and I think they succeed fairly well, but there might be
315bugs and rough edges. I know that some are just broken because, for
316actual correctness, declarations provided by the caller need to be split
317up into a number of different parts of the expansion, which in turn
318requires figuring out what the declarations mean and which bindings
319they're referring to. That's not completely impossible, assuming that
f458e64e 320there aren't implementation-specific declarations with crazy syntax
1528431b
MW
321mixed in there, but it's more work than seems worthwhile.
322
323
324* COMMENT Emacs cruft
325
326#+LATEX_CLASS: strayman
327
328## LocalWords: CLOS ish destructure destructured accessor specializers
a1b51e19 329## LocalWords: accessors DSLs gensym gensyms
1528431b
MW
330
331## Local variables:
332## mode: org
333## End: