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