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