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