Paul Dundon’s Weblog


A little cheese and a little whine

Five Reasons to Look at Lisp

As a programmer, I’ve met more than one colleague who’s recommended I learn Lisp. Lisp, they say, is the best language they’ve ever worked in. When pressed, however, they find it difficult to articulate why, saying I really have to learn the language to appreciate why it’s worth learning. Despite my appreciation of recursion, I’ve never found this position especially compelling.

Over the last few months I’ve been writing a lot of commodity web applications – basically front-ends to databases. Last weekend the boredom finally became too much and I decided I needed more of a challenge. So I started making my way through Practical Common Lisp and the lectures on Structure and Interpretation of Computer Programs.

As a result, I think I can articulate why Lisp is worth learning (and I have to say, it isn’t hard to master the basics). I’m only a beginner, and more experienced Lisp users will no doubt have a much better view. But for anyone who’s looking to understand quickly what all the fuss is about, here are a few pointers:

  1. Lisp syntax is very simple and very regular (if a bit befuddling at first). This means that the advanced features it shares with other relaxed-type languages like Javascript and Python are easier to use. For example, Lisp treats functions as first class citizens, allowing us to break programs into high-level strategies and low-level procedures. We can write functions which return functions, which might be curried versions of other functions (ie, versions with one or more parameters already bound). Other languages do this but Lisp’s syntax makes it natural and intuitive. Similarly, recursion feels much more natural in Lisp than in some other languages.

    As an example, consider the (inevitable) Fibonacci function, in Lisp:

    (defun fib (x)
    	(if (= x 1) 1
    		(if (= x 2) 2
    			(+ (fib (- x 1)) (fib (- x 2))))))

    Parentheses are used to enclose everything that needs to be evaluated, allowing a quick visual breakdown of the code; prefix notation (= x 1 rather than x=1) keeps the syntax regular; and defining if as a function rather than a control structure eliminates a lot of syntactic sugar.

  2. Lisp code can easily be represented as data. The .NET languages have this feature, but while CodeDom is an arcane art to all but the most dedicated, the simplicity and regularity of Lisp syntax means that it takes only a few minutes to understand the relationship between code and code-as-data. Lisp has a “macro” system which is in fact a code generator; a macro is a Lisp function which takes Lisp-like code and returns actual Lisp code. Macro “expansion” takes place before code execution and continues until no macros are left unexpanded (since macros can generate other macros). This makes it possible to define domain-specific languages (so long as they share the basic Lisp syntax) at least an order of magnitude more easily than in languages like VB or Java.
  3. Lisp typically runs in an interactive environment, allowing very rapid re-definition of functions, macros etc. Sitting in front of a Lisp prompt you can define, and progressively refine, a domain specific language for the class of problem you want to solve while at the same time using it to solve some specific problem(s).
  4. Object orientation in Lisp is based around a set of mechanisms which are more abstract and powerful than languages in the Smalltalk lineage. I have to confess that I haven’t fathomed these yet.
  5. Lisp’s exception handling mechanism includes the concept of a restart, which effectively names a block of code to be executed in a specific exception handler. We can bind the restart to a specific block of code in a higher level function than the exception is caught in. For example, if we write a library with a function which depends on opening a file part way through a much longer process, we might not want to unwind execution to the top of the stack (and the start of that process) if the file is missing; it might be better to prompt the user for another location for the file. However, we may want to run the code in context where a prompt is inappropriate. Restarts allow us to define these two different ways of handling the error and bind them, as we need, to the low-level exception handler.

Lisp doesn’t look particularly good for the sort of commodity web application where you take data off a form and shovel it into a database (although it’s no worse than, say, PHP for that purpose; and it would probably be fantastic for generating such applications from an abstract representation). It comes into its own when you’re solving a novel problem, typically a problem which revolves around complex transformations of data. It looks especially useful where you want to explore the consequences of using different transformations to solve a class of problems.

I’ve only spent a few days with Lisp; however, I think I can see already why people who love Lisp really love it. Lisp lets you do things naturally which in other languages feel like bolt-ons; it lets you do things easily which in other languages require arcane syntax or code patterns. The language gets out of the way when you’re doing things which are themselves conceptually demanding, where other languages make already complex tasks even more daunting because of the clumsiness of the syntax. All these features make it pragmatically very satisfying. These benefits emerge from the foundations of the language – they are side effects of the elegance of its syntax and approach. The ability to define domain specific languages isn’t an afterthought or even what looks like a design goal; it’s an emergent property of the language fundamentals. That adds a killer level of aesthetic satisfaction which makes one feel that Lisp isn’t just powerful, but fundamentally beautiful.


Filed under: Tech

5 Responses

  1. Jake Voytko says:

    The “code as data” idea goes deeper than you think. Ron Rivest (of RSA fame) has created a method for storing arbitrary data in s-expressions: , and there is some press from people like Yegge of using Lisp as the output of all of your programs (why parse error logs when you can just use (READ)?)

  2. Any reason you call Lisp LISP?

  3. pauldundon says:

    No reason for “LISP” apart from a capitalization frenzy (which seems quite the rage). Thanks for pointing it out.

  4. foo says:

    numbers are compared with = and not with EQ

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 13 other followers

My Bookshelf

The Golden Bough
The Value of Nothing
The Fire
A Wolf at the Table
Devil Bones

My links

%d bloggers like this: