1 "In truth, I found myself incorrigible with respect to *Order*; and
2 now I am grown old and my memory bad, I feel very sensibly the want of
3 it. But, on the whole, though I never arrived at the perfection I had
4 been so ambitious of obtaining, but fell far short of it, yet I was,
5 by the endeavour, a better and happier man than I otherwise should
6 have been if I had not attempted it; as those who aim at perfect
7 writing by imitating the engraved copies, though they never reach the
8 wished-for excellence of those copies, their hand is mended by the
9 endeavor, and is tolerable while it continues fair and legible."
10 -- Benjamin Franklin in his autobiography
12 "'Signs make humans do things,' said Nisodemus, 'or stop doing things.
13 So get to work, good Dorcas. Signs. Um. Signs that say *No*.'"
14 -- Terry Pratchett, _Diggers_
16 There are some principles which I'd like to see used in the
18 1. conforming to the standard
20 a. removing stale code
21 b. When practical, important properties should be made manifest in
22 the code. (Putting them in the comments is a distant second best.)
23 i. Perhaps most importantly, things being the same (in the strong
24 sense that if you cut X, Y should bleed) should be manifest in
25 the code. Having code in more than one place to do the same
26 thing is bad. Having a bunch of manifest constants with hidden
27 relationships to each other is inexcusable. (Some current
28 heinous offenders against this principle are the memoizing
29 caches for various functions, and the LONG-FLOAT code.)
30 ii. Enforcing nontrivial invariants, e.g. by declaring the
31 types of variables, or by making assertions, can be very
33 c. using clearer internal representations
35 A. more-up-to-date names, e.g. PACKAGE-DESIGNATOR instead
36 of PACKAGELIKE (in order to match terminology used in ANSI spec)
37 B. more-informative names, e.g. SAVE-LISP-AND-DIE instead
38 of SAVE-LISP or WRAPPER-INVALID rather than WRAPPER-STATE
39 C. families of names which correctly suggest parallelism,
40 e.g. CONS-TO-CORE instead of ALLOCATE-CONS, in order to
41 suggest the parallelism with other FOO-TO-CORE functions
42 ii. clearer encodings, e.g. it's confusing that WRAPPER-STATE in PCL
43 returns T for valid and any other value for invalid; could
44 be clarified by changing to WRAPPER-INVALID returning a
45 generalized boolean; or e.g. it's confusing to encode things
46 as symbols and then use STRING= SYMBOL-NAME instead of EQ
48 iii. clearer implementations, e.g. cached functions being
49 done with HASH-TABLE instead of hand-coded caches
50 d. informative comments and other documentation
51 i. documenting things like the purposes and required properties
52 of functions, objects, *FEATURES* options, memory layouts, etc.
53 ii. not using terms like "new" without reference to when.
54 (A smart source code control system which would let you
55 find when the comment was written would help here, but
56 there's no reason to write comments that require a smart
57 source code control system to understand..)
58 e. using functions instead of macros where appropriate
59 f. maximizing the amount of stuff that's (broadly speaking) "table
60 driven". I find this particularly helpful when the table describes
61 the final shape of the result (e.g. the package-data-list.lisp-expr
62 file), replacing a recipe for constructing the result (e.g. various
63 in-the-flow-of-control package-manipulation forms) in which the
64 final shape of the result is only implicit. But it can also be very
65 helpful any time the table language can be just expressive enough
66 for the problem at hand.
67 g. using functional operators instead of side-effecting operators
69 h. making it easy to find things in the code
70 i. defining things using constructs which can be understood by etags
71 i. using the standard library where possible
72 i. instead of hand-coding stuff
73 (My package-data-list.lisp-expr stuff may be a bad example as of
74 19991208, since the system has evolved to the point where it
75 might be possible to replace my hand-coded machinery with some
77 j. more-ambitious dreams..
78 i. fixing the build process so that the system can be bootstrapped
79 from scratch, so that the source code alone, and not bits and
80 pieces inherited from the previous executable, determine the
81 properties of the new executable
82 ii. making package dependencies be a DAG instead of a mess, so
83 the system could be understood (and rebuilt) in pieces
84 iii. moving enough of the system into C code that the Common Lisp
85 LOAD operator (and all the symbol table and FOP and other
86 machinery that it depends on) is implemented entirely in C, so
87 that GENESIS would become unnecessary (because all files could
90 a. In this vale of tears, some tweaking may be unavoidably required
91 when making software run on more than one machine. But we should
92 try to minimize it, not embrace it. And to the extent that it's
93 unavoidable, where possible it should be handled by making an
94 abstract value or operation which is used on all systems, then
95 making separate implementations of those values and operations
96 for the various systems. (This is very analogous to object-oriented
97 programming, and is good for the same reasons that method dispatch
98 is better than a bunch of CASE statements.)
99 4. making a better programming environment
100 a. Declarations *are* assertions! (For function return values, too!)
101 b. Making the debugger, the profiler, and TRACE work better.
102 c. Making extensions more comprehensible.
103 i. Making a smaller set of core extensions. IMHO the high level
104 ones like ONCE-ONLY and LETF belong in a portable library
105 somewhere, not in the core system.
106 ii. Making more-orthogonal extensions. (e.g. removing the
107 PURIFY option from SAVE-LISP-AND-DIE, on the theory that
108 you can always call PURIFY yourself if you like)
109 iii. If an extension must be complicated, if possible make the
110 complexity conform to some existing standard. (E.g. if SBCL
111 supplied a command-line argument parsing facility, I'd want
112 it to be as much like existing command-line parsing utilities
115 a. improving compiled code
118 iii. better compiler optimizations
120 b. increasing the performance of the system
122 ii. improved ability to compile prototype programs fast, even
123 at the expense of performance of the compiled program
125 i. more graceful handling of stack overflow and memory exhaustion
126 ii. improving interrupt safety by e.g. locking symbol tables
127 d. decreasing the size of the SBCL executable
128 e. not breaking old extensions which are likely to make it into the
130 6. other maybe not-so-nice things
131 a. adding whizzy new features which make it harder to maintain core
132 code. (Support for the debugger is important enough that I'll
133 cheerfully make an exception. Multithreading might also be
134 sufficiently important that it's probably worth making an exception.)
135 The one other class of extensions that I am particularly interested
136 is CORBA or other standard interface support, so that programs can
137 more easily break out of the Lisp/GC box to do things like graphics.
138 ("So why did you drop all the socket support, Bill?" I hear you
139 ask. Fundamentally, because I have 'way too much to maintain
140 already; but also because I think it's too low-level to add much
141 value. People who are prepared to work at that level of abstraction
142 and non-portability could just code their own wrapper layer
143 in C and talk to it through the ALIEN stuff.)
145 a. Sharp, rigid tools are safer than dull or floppy tools. I'm
146 inclined to avoid complicated defaulting behavior (e.g. trying
147 to decide what file to LOAD when extension is not specified) or
148 continuable errors, preferring functions which have simple behavior
149 with no surprises (even surprises which are arguably pleasant).
151 CMU CL maintenance has been conservative in ways that I would prefer to
152 be flexible, and flexible in ways that I'd prefer to be conservative.
153 CMU CL maintainers have been conservative about keeping old code and
154 maintaining the old structure, and flexible about allowing a bunch of
155 additional stuff to be tacked onto the old structure.
157 There are some good things about the way that CMU CL has been
158 maintained that I nonetheless propose to jettison. In particular,
159 binary compatibility between releases. This is a very handy feature,
160 but it's a pain to maintain. At least for a while, I intend to just
161 require that programs be recompiled any time they're to be used with a
162 new version of the system. After a while things might settle down to
163 where recompiles will only be required for new major releases, so
164 either all 3.3.x fasl files will work with any 3.3.y runtime, or all
165 3.w.x fasl files will work with any 3.y.z runtime. But before trying
166 to achieve that kind of stability, I think it's more important to
167 be able to clean up things about the internal structure of the system.
168 Aiming for that kind of stability would impair our ability to make
170 * cleaning up DEFUN and DEFMACRO to use EVAL-WHEN instead of IR1 magic;
171 * reducing the separation between PCL classes and COMMON-LISP classes;
172 * fixing bad FOPs (e.g. the CMU CL fops which interact with the *PACKAGE*