How Common Lisp sucks

Two things to get out of the way at the outset:

1. Note that the title of this post is *HOW* CL sucks, not *WHY* it
sucks. The difference is significant. Please take the time to
understand it before you flame me.

2. I'm not going to say anything I haven't said a thousand times
before, so those of you who know me (that means you, Kenny) will not
find anything new here so you may as well not even bother.

I am writing this because of the debate surrounding Steve Yegge's recent
blog entries on Lisp. It is unfortunate that he made so many technical
mistakes in his posts because they distract people from the fact that
underneath all the errors he is actually making a valid point, that
being that CL has very significant problems that are barriers to its
adoption. (Some people think this is a feature, that having a few
obstacles to overcome keeps out the rif raf. I suppose this is a
defensible position, but I don't subscribe to it.)

I'm going to point out just three problems with CL. There are more.
None of these are original observations.

1. CL lacks standardized support for many operations that are
necessities in today's world (e.g. sockets, database connectivity,
foreign functions). Moreover, it lacks any mechanism by which these
features could be standardized. It is claimed that there are portable
libraries that work across implementations that provide de facto
standards, e.g. UFFI, but these claims are false. I don't have time to
get into details at the moment, but the fact of the matter is that
trying to use Lisp for e.g. writing a Web server is an incredibly
painful experience compared to doing the same thing in e.g. Python.

The Balkanization of the CL implementation space also has the
consequence that one must choose between using implementation-specific
features and thus limiting the potential audience for one's code to a
niche within a niche, or writing to the least common denominator, which
generally means writing an awful lot of #+ reader macros.

2. Even for the one thing that CL claims to be particularly good at --
as a platform for embedding domain-specific languages -- it has
significant limits. To embed languages that differ from CL's semantics
in certain ways requires significant effort. To cite but one example: I
would like to embed a language that is very similar to Common Lisp, but
which differs in how it handles global variable references (to use
global lexical environments) and ((function-returning-a-function)
arguments) syntax. The former can be done using symbol macros, but only
if the top-level definitions precede their first use. If you reference
a global before defining it then you're screwed. The latter cannot be
done at all within CL unless you write a full code walker. But adding
this capability is utterly trivial within an implementation. In MCL it
takes two lines of code. And if it were done it would result in
strictly greater expressive power. Furthermore, it is not even
necessary to agree on the semantics of ((...) ...). One could simply
add a new macro defining form (or even a global variable) to set a
user-definable hook for transforming expressions whose CARs are lists
that do not begin with LAMDBA. All that would need to be agreed upon is
the name of this form. Furthermore, this would result in strictly
greater expressive power. It would be strictly backwards-compatible.
And It would serve the needs of a number of users who are not currently
being served (e.g. those who prefer to do functional-style programming
without having to type FUNCALL all the time.)

But despite the fact that this change is easy and only good could come
of it, it does not happen because there is no process by which this
change can be effected (which is, I believe, a direct consequence of the
fact that the realities of CL politics are that CL is utterly resistant
to all change, though I would dearly love to be proven wrong on that).

(Oh, and anyone who wishes to prove me wrong, please not that there is a
big big difference between effecting change in CL and effecting change
in an implementation of CL.)

3. Much of CL's core is badly designed. For example, consider NTH and
ELT. The functionality of ELT is a strict superset of NTH, so why have
NTH cluttering up the language? (To say nothing of the fact that the
order of the arguments in these two functions are gratuitously
reversed.) Why is the function that computes the difference of two sets
called SET-DIFFERENCE, but the function that computes the intersection
of two sets called simply INTERSECTION? And why do all of these
functions operate on lists, not sets? It's because there are no sets in
CL, which means that CL leads one to prematurely "optimize" sets as
lists. (I put optimize in scare quotes because in fact this is rarely
an optimization, especially when your sets get big, and most of the time
you have to go back and rip out huge chunks of code to replace your
lists with hash tables or binary trees.) I could go on and on.

Now, for those of you who wish to respond I ask you to keep in mind the

1. The details of my criticisms are mostly irrelevant. What matters is
that CL is far from perfect, and that it has no mechanism for change.
So don't bother picking a nit about one of my specific criticisms unless
you wish to argue that CL is perfect and doesn't need to change.

2. I know a lot more about Lisp that Steve Yegge. I spent twenty years
programming in Lisp for a living. I have authored some highly
referenced papers on Lisp. I am far from the world's foremost expert,
but I'm no newbie. If you think I'm wrong about a technical point you
should think twice.

3. I do not hate Lisp. It is and has always been my favorite
programming languages. My love for Lisp pretty much destroyed my career
as a programmer. My motivation for criticising Lisp is not to convince
people not to use it. It is to effect changes that I believe are
necessary to get more people to use it. To quote Paul Graham, "It's not
Lisp that sucks, it's Common Lisp that sucks." And actually, I would
soften that somewhat: it's not Common Lisp that sucks, it's some parts
of Common Lisp that suck. But make no mistake, some parts of Common
Lisp really do suck, and unless they are fixed a lot of people -- myself
included -- won't be able to use it even though they may want to really