1 November 2005
With Lisp, coding is no longer the bottleneck. This is in part due to the unencumbered syntax, in part due to hygienic macros, in part lazy versus eager evaluation at the discretion of the coder on a per-definition basis, closures, dynamic & lexical scope, etc., etc. Most importantly, you get all this plus no matter how much you use it, it’s never dull.
Lisp makes programming fun again.
Why are macros so important to Lisp programmers? … Because Lisp is its own metalanguage, the power of the entire programming language can be brought to bear on the task of transforming program text. …
Why settle for anything less than the full programming language itself?
–Gabriel & Steele The Evolution of Lisp, p78.
Calling it the granddaddy of programming languages would be bad metaphor.
Yes, Lisp predates most other languages. It’s true that many other dynamic languages start out by being simple yet around the decade mark, seem to each add sufficient complexity such that one can see how these others– e.g., Perl, Python, PHP– attempt to bolt-on features that are first class elements of Lisp. Others that begin as a simplified or 80% Lisp– such as Ruby– still leave us wanting things like macros.
Why wait for certain ideas to be reintroduced when they’re already available in Lisp?
Retro-futuristic hype of the mid-twentieth century sold us on the idea that computers were supposed to make life better– better, by speeding-up mundane tasks and taking the human out of the loop of tedious, repetitive actions.
Lisp also emerged during that era, having appeared for the first time in 1958, but it’s changed significantly over the years in ways that maintain a certain consistency, making it perhaps the most appropriate choice among languages today for the majority of programming.
This is about asking, critically: Why use one language over another?
For many, it’s a short list: need a specific library, the tools work on a particular platform, familiarity and one’s ability to hit the ground running, etc.
If you’re well paid to use Java or Cobol and you enjoy it, by all means, stick with it. For those whom the Perl way jives with your way of life, then good for you.
Pause for a moment, and step outside yourself. What would you like in a language today? Let go for the moment that you might be considered senior level in one particular language, that you command a certain salary due to proficiency or that you no longer need to pick up a reference manual.
You probably have the computer working for you while writing code: syntax highlighting, auto-indent, auto-completion of words and presenting context sensitive descriptions of functions and parameters while typing are each a big part of it.
But enough about Emacs.
Now take it to the next level: the language.
Lisp provides the ability to customize interactions with your own code by offering macros– unlike anything familiar to C coders. Lisp macros are more like using an API in your favorite language to generate code during the compilation phase and/or while loading and/or during execution but in ways that the analogy breaks down.
It’s something best experienced for yourself.
Since much has been written on the subject, I’ll defer to Richard Gabriel’s Art of Lisp essay, Paul Graham’s various essays, Peter Seibel’s excellent book and Peter Norvig’s… well… experience.
After all, why listen to me? I’m not looking to convert or persuade anyone. If you’d rather stick with your long-time favorite language, that’s fine with me! People have asked why lisp, and this weak essay covers the bulk of my answer.
I found myself having taken a tour of other languages over twenty years only to use them as the basis of making an informed decision to select Lisp now.
As with many others, I used one dialect of Lisp or another in various
unrelated jobs and to fill specific needs. For me, it started with
technical drawing and CAD. I picked up AutoLisp in 1987 to create an
automated slide-show to present my portfolio for national competition.
Then, mine, like many universities from mid-eighties through nineties,
relied upon Scheme for first year courses. When working from home, partly
to avoid sticky keyboards on campus, noisy dial-up lines (as in connecting
directly to a host or terminal server, long before PPP or DSL) demonstrated
the need for 800 levels of undo that Emacs offered over
single item history. And so, in 1989, I embarked upon what might be a
lifetime of using “the lisp engine that allows you to edit text too.”
Bias aside– now that you have my full disclosure– choosing Lisp is appropriate for far more than just one’s history or comfort level.
Personally, I thrive on the challenges of trying new things.
I picked up C in 1986 after reading Peter Norton’s article in PC Magazine a few months prior regarding the use of that language to build “industrial strength” applications. For me, it was a huge improvement, regardless of my fondness for Borland TurboPascal 3.0. Having been one of relatively few high school students at the time who was paid to program, this was about investing in my budding career.
Then C++ came into my life toward the end of that decade. It was new; it was the next best thing. Actually, I was young and– despite having operated my own single product software company– relatively inexperienced.
After getting burned by multiple inheritance not yet working in GNU
g++, I took what I learned in that language and returned to C
for real work.
At that time, you couldn’t really use C++ without being
aware of how Bell Labs'
CFRONT program translated to C.
So then, passing objects explicitly as the first parameter to a related set
of functions came easily. I used Emacs for code generation via regular
expressions and elisp, all based upon my misunderstanding of (then)
templates. Exceptions were via
#define substitutions, the
few times I needed them. Perhaps most importantly, I had much prior
experience with function pointers in C for run-time dynamic behavior.
Little did I know that my use of “C with explicit objects” was essentially generic programming.
In Lisp, generic methods are an abstraction beyond the familiar dot notation of object oriented, message passing languages like C++, Java, Python, Ruby, etc.
Over the years, while making rapid prototypes, I later observed my habit of using nested lists for quick data structures. Nested lists within languages like Perl or Python come naturally and provide an ease of understanding the code. Understanding the code was especially important when I knew I’d be writing it, yet someone else would have to maintain it long after I was gone.
For efficiency, these lists would sometimes be pre-processed into some other structure before entering the main execution cycle.
About the time I picked up C++, I had abandoned AutoLisp. The little CAD consulting work I had then was more as systems administrator. Looking back, my use of AutoLisp was equivalent to using Bash or other shell scripting languages.
Emacs Lisp, like AutoLisp, is another Lisp-1 dialect. Common Lisp is Lisp-2, and the changes made final by ANSI in December 1994 are well worth giving it another look.
Even though I dismissed Paul Grahams' book when it first came out in 1995, I’m without regret for my tour of other languages.
C++, Perl, Python, Ruby– each taught me some new way to approach particular problems.
After all, a language is just a tool, and it’s experience that ultimately brings us across the finish line, but a better tool just makes the journey so much more pleasant!
Pick up a copy of Peter Seibel’s wonderful Practical Common Lisp, and see for yourself.
Here are links that were useful to me while learning: http://play.org/links/lisp-intro
* * *
Having used Lisp early in my career for sufficiently complicated utility programming then sampling it again during its ANSI standards process and finally going deep for hard-core systems programming after twenty years experience at large, I clearly recognize nearly everything else as merely quaint academic toys that escaped the lab (sometimes helped by fierce marketing), transportable assembly language or messy glue.
I include C++ and Java in the academic toy category; C as it’s always been promoted is indeed portable assembly; and others like Bash/Perl/Ruby/Python are glue– the kind that makes your fingers stick together as well as everything it happens to touch. (Perl5 is just duct tape and bailing wire.)
Others that happen to date back to the late 1950’s still exist only for legacy reasons. Perhaps for historical perspective or like those tinkering with antique cars, a few still pursue these merely as enthusiasts.
Lisp, on the other hand, is experiencing a renaissance in the early twenty-first century.
While developers who use other languages often talk about what they’ll do once escaping the business, all the Lisp people I know so thoroughly enjoy their craft that many intend continuing as long as physically able.
* * *
By “Lisp”, I specifically mean the path through ANSI Common Lisp and what’s
yet to come through Lispniks. Haskell and Scheme attempt to be too pure for
my tastes, and with the seventh major revision of Scheme now out, I agree
with Pascal Bourguignon on
comp.lang.lisp, “Perhaps R9RS will be
indistinguishable enough from CL that I’ll be able to use it.” I haven’t
used OCaml, as limitations of its macro system was enough to reject it.