Every programming language has idioms–patterns used so frequently that they are almost considered part of the language itself. (See these C idioms for examples.) Common Lisp, with almost unlimited possibilities for syntax, depends more heavily on idioms to remain comprehensible. Some examples are
define-something for definitions,
something-p for predicate tests, and
make-something for constructors.
Marco Antoniotti created a clever macro package called DEFINER that codifies the most common of these, definitions, into a single macro with consistent syntax for any object that is being defined. With DEFINER, all definitions can be made with a single macro:
def, which is followed by a symbol specifying what is being defined. So
def var, and
Of course, this is Lisp, so
def can be turned on itself to produce new definition forms with
def definer. New
def forms can then be created that follow the same syntactic pattern of:
(def type-of-thing name properties...)
As Marco writes, DEFINER “makes it possible to homogeneize a natural programming practice followed by several CL programmers.”
I say, why not extend this practice to other idioms? Here’s a list of other Common Lisp idioms I think could be well-served by the same sort of homogeneization:
with thingto delimit the scope of certain things–local variables, special variables, functions, open files, etc. Then
with functions, and
- A generic constructor for any anonymous (unnamed) object. This could ensure that all object constructors follow a predictable pattern after
make instance, and turns
lambdainto the infinitely more readable
make function. Also begs the question of why one can’t create anonymous classes.
- A generic predicate, borrowed from the FiveAM testing framework. Should alway return a boolean true/false value. Gives us the more readable
is eveninstead of
- Replace Lisp’s scattering of equality predicates–
string=, etc.–with forms like
equal number, and
equal string. One could alternately use
is equal, although that looks odd in English grammar.
- A generic type converter. Makes it more obvious, for example, when
stringis being used as a type specifier and when as a coercion function. Also makes it very easy to define new converters between types, assuming these are implemented as generic functions.
- Generic accessor. Replaces both primitives like
caras well as object-related functions like
- Replacement for
getform should have a corresponding
set. Primitives like
And of course, to top it off we would want
def equality, and
def as. And while we’re at it,
The point of all this is to make code more readable. One can reduce the 978 Common Lisp symbols to pairs of symbols, the first naming the general category of operation and the second specifying the exact operation within that category.
When examining unfamiliar code that uses these idiomatic macros, a programmer can look at the categorical names to get a rough idea of what is happening even without knowing about the specific functions being used. This can make Common Lisp more manageable without sacrificing any of its expressiveness.