Tim Bradshaw

What goes where

For a long time I’ve been confused about where various bits of my Lisp code should go. In particular what’s a ‘hack’, what’s a ‘tool’ and what should have its own existence? I think I’ve probably sorted it out now, so here’s my current idea. Probably this is not interesting to anyone who is not me, but I wanted to remember.

Prefer modules over systems

Although many things have separate system definitions, I almost never use them: they only exist to make life better for people who live in the ASDF world. For almost all purposes I use require-module and its tools for almost everything: A source file saying (needs :org.tfeb.hax.iterate) is just far easier to understand than a vast system definition file1. This applies even for multi-file things.

Modules provide their names, and live in packages with the same name they provide. Always use heirarchical package names so require-module knows where to look.

Collections of modules, like hax, traditionally have some system definition which will compile & load all of them, and perhaps run all the tests. But that’s all it’s for: there’s no useful reason to do this normally: just load the modules as you need them (or, well, as you need them).

Minimize the number of repos

I don’t want thousands of public repos. Particularly this is true because almost all of this stuff comes from a single internal repo, and each publication repo requires its own little bit of glue to make it work2.

In particular I’m completely fine with there being more than one ‘system’ per repo.

Any complete program should have its own repo

So anything you might run from the command line or wherever should have its own repo. For instance warranted has its own repo.

Modifications to CL get their own repos

Anything which redefines bits of CL gets its own repo. An example is conduit packages, which redefines defpackage & other package-related functionality.

Any single entity which is more than one file gets its own repo

An example is reeder. ‘More than one file’ excludes the system definition file where there is one.

Single-file systems & modules

Things for program construction live in tools

These are things that might help you build programs, such as require-module and its associated command. Each module has an ASDF defsystem for compatibility, autogenerated.

Things for for use in programs are hax

These are things which might help you write stuff. Some of these might be fairly elaborate, such as collecting & its relations. Again each module has an ASDF defsystem for compatibility.

Things which are less serious are toys

Some of these will make their way elsewhere. Toys are all modules. Nothing other than toys can depend on toys (this is important).

An example: slog

slog is currently a toy, as it’s perhaps not complete and certainly not tested. It’s not enormous but it’s also not tiny. It is also a standalone module: it depends on some other modules but it’s a thing you might well want to load on its own. But it’s not a program: it’s part of a program. So it will end up as a hack, not in its own repo3.

  1. This is how Racket puts systems together for instance, and largely how Python does as well, if I remember. It’s just a better approach to let a system’s source files describe their own needs in my view. And ASDF is just … ick. 

  2. There’s no chance the internal repo will get published as it has a large amount both of of idiosyncratic code and things I just don’t want to be public. So don’t ask. 

  3. Before it does, simple-loops will need to be promoted however.