Everything You Need To Get Started With Common Lisp

This post was written by Jake on December 29, 2008
Posted Under: Computer Science,Programming,Programming Languages,Tutorial

Quick-Links for the TL;DR Crowd

About Lisp: Describes Lisp as an overview.
High Level Overview: Describes in general what is needed to program with Lisp.
All you need

Code examples: A few rudimentary Lisp snippets.
Other Lisp Features: Features that I did not feel like explaining :)
Resources

About Lisp

Note: For a complete introduction, I recommend this e-book. If you only want to learn enough to get started, read on!

Interactive

Most languages take an input file and produce an executable or run a script. Lisp is interactive: all input is entered into the REPL, and the computation’s result is printed to the screen.

REPL: Read Evaluate Print Loop. A C++ coder can think of it like this:

void lisp()
{
    while(true){
        cout<<">"; // prompt
        cout<<evaluate(read())<<endl;
    }
}

If you’ve ever used Python’s command line prompt, you’ve used a REPL. A bash prompt is a REPL. So is Lisp.

Prefix

Most expressions in C-style languages are prefix, but exceptions are made for arithmetic, such as 1/(x+3). All expressions in Lisp are prefix expressions: the first argument of an S-expression (Sexp) is a function name, and the rest of the atoms of the S-expression are the arguments for the function. The following are examples of Lisp function calls:

(/ 1 (+ x 3))         ; 1/(x+3)
(format t "~A~%" x)    ; prints the value of 'x' and a newline.

All Expressions Return Values

All expressions in Lisp return values. For instance, the ‘if‘ statement in Lisp not only chooses which execution branch to follow, but returns the result of the executed expression. ‘nil‘ is the default return value of an expression, which also evaluates to false (‘t‘ is true).

In C-style languages, expressions don’t necessarily return values. The expression ‘1+3‘ will return ‘4‘, but cout<<1+3‘ doesn’t return anything (They return a reference to an ostream, so this is a mistake) void functions don’t return anything; they can’t be used as a sub-expression for a larger statement of code.

Functions in Common Lisp can return multiple values. The ‘multiple-value-bind‘ macro is used to bind multiple return values to multiple variables.

High Level Overview: What You Need To Get Started

1) An implementation. All you need is an implementation that conforms to the standards. All of them have an edge case or two, but odds are it won’t affect you. If you absolutely need to switch later (for CLisp’s fast arbitrary precision arithmetic, for instance), nothing is stopping you; most libraries support all popular implementations.

2) An editor. I personally recommend Emacs with the SLIME extension. You can also use Vim and Limp if you either prefer Vim or you can’t stand Emacs. I left Vim before I started using Emacs, so I’ve never used Limp. Caveat emptor!

You don’t absolutely need to use an editor that interacts with Lisp. It’s POSSIBLE to run a Lisp program like a script, but it usually makes as much sense as opening a bag of chips with a hammer. You will want to use the REPL for most of your Lisp tasks, and this will only be bearable from within a good editor.

3) A Lisp tutorial or reference. I highly recommend “ANSI Common Lisp” by Paul Graham [see my review].

4) An installation system, like asdf-install. Installation systems automatically load Lisp projects into your current image, and are essential for working with a large project. asdf-install allows you to download libraries from cliki.net and load them into your Lisp image from within the interactive Lisp command prompt!

Details: What You Need To Get Started

SBCL

About

Steel Bank Common Lisp (SBCL) was forked from Carnagie-Mellon University Common Lisp (CMUCL) in 1999. It is named after Carnagie and Mellon’s respective industries, steel and banking.

Most Lisps can be interpreted or compiled, depending on the context. However, SBCL compiles all Lisp code it receives. Having used SBCL for 6 months or so, there’s not much of a pause even for large Lisp files. On the other hand, the compiler is very verbose, but this can be tweaked.

Why SBCL: Popular

Naturally, I can’t find good numbers on the popularity of SBCL. However, it is noteworthy that asdf-install and LIMP were initially designed to work with SBCL. This seems to be par for the course for all of the libraries I’ve used.

Why SBCL: Active Development

Development of SBCL is still roaring along, with 1,228 commits to their Sourceforge page at the time of writing, including several in the past few weeks. New releases come at the beginning of every month, and this month was no exception: version 1.0.23 was produced December 1, 2008.

Installing SBCL

Installing SBCL: Linux

SBCL can be installed like any other package:

sudo aptitude install sbcl
# Or your local variant.

Once that’s finished, it’s easy to test the installation:

jake@justalaptop:~/code/genesis$ sbcl
(+ 2 2)
*
4

Installing SBCL: Windows

There is an “experimental” Windows installation binary: [link].

I’ve ran it for brief periods and it seems to work fine, so I’m not sure what’s so experimental about it. Again, Caveat emptor!

After installation, run SBCL. You will get a command-line prompt, and type the following:

&gt; (+ 2 2)
*
4

It works!

Emacs

You can use whatever editor that you want to write Lisp. Emacs has good advantages:

ELisp: Emacs is scripted in its own subset of Common Lisp. Called ‘elisp’, anybody who has been working with Lisp for a few months and can type “ELisp manual” into Google can customize Emacs to their taste.

Irony alert: I typed “elisp manula” into Google on my first try.

Automatic indentation: Yeah, I know, every editor in the history of the world does automatic indentation. However, Emacs’ authors primarily write Lisp code, so they paid close attention to how Emacs interacts with Lisp. I rarely see Emacs do the Wrong Thing. When it does, I’m usually writing awful code.

SLIME: The Superior Lisp Interaction Mode for Emacs. In order to effectively code in Lisp, you need an editor mode that will interact with a Lisp implementation. Typing the code directly into a command line is nice for small experiments, but is painful for anything more than 30 lines of code (for me at least.. your pain tolerance may vary).

SLIME

SLIME combines the editing power of Emacs with the interactive nature of Lisp.

If you’ve ever used Python’s command-line prompt, you’re aware that it’s painful to use for any amount of time. The editing capability is limited to that of your console, and when you exit Python, all of your code disappears!

SBCL (and all other Lisp implementations) is no different. If this were the only option for working with Lisp, nobody would. You must work with the REPL from within a real editor. You COULD write code in an external file and load it into SBCL from the command line, but that removes the interactive nature of Lisp.

Enter SLIME (Superir Lisp Interactive Mode for Emacs). SLIME spawns a new Lisp process and acts as the liaison between you and the process.

To start the whole process, just type “M-x slime“, and a new REPL buffer opens. Any Lisp command can be entered into this buffer, and you get all of the editing commands from Emacs. slime-mode begins in all of your open Lisp buffers, which gives you code completion and function argument hints for all compiled functions.

If slime-mode is enabled in a Lisp buffer, you can compile the file with “C-c C-k“, or compile a single function with “C-c C-c” (it looks to me like dependencies are propagated correctly). SLIME knows what capability your Lisp has, so it can take advantage of implementation-specific capabilities like debugging.

Installing SLIME

SLIME is installed the same way as any other Emacs plugin:

  • Download and extract.
  • Add the load path to your .emacs file
  • Add any other code snippets required.

In this case, you’re going to be adding the following code to your .emacs file (open using “M-x M-f ~/.emacs“):

(add-to-list 'load-path "<em>/the/path/to/slime</em>")
(require 'slime)
(add-hook 'lisp-mode-hook (lambda () (slime-mode t)))
(add-hook 'inferior-lisp-mode-hook (lambda () (inferior-slime-mode t)))
(setq inferior-lisp-program "sbcl")

I haven’t tested it on Windows, so I’m not sure if there are any extra gotchas. If you find that you’re running into undefined function errors, one possible workaround is to install Cygwin and add C:\cygwin\bin and c:\cygwin\usr\bin to your %PATH% environment variable. Some people run away in horror at the idea, so if you don’t like it, you’re on your own.

asdf-install

One thing that you should research is asdf-install, a package manager for Lisp. If you find that you need a package that is found on cliki.net, you can download it with one step:

&gt; (require 'asdf-install) ; Not the one step.
("ASDF-INSTALL")
&gt; (asdf-install:install 'postmodern) ; The one step.
NIL

The above installs Postmodern, a simple Postgres interface for Common Lisp. Once you’ve done this, you only need to load the package into your Lisp image. This is also accomplished using asdf-install:

&gt; (asdf:oos 'asdf:load-op :postmodern)
NIL

Using those 3 lines, you can now start to define database connections and operations on the database, without ever leaving Emacs!

Starting to Code

I highly recommend that you find a real reference or a real tutorial and start using that to write code. However, if you’re looking for things to enter into the REPL, I’ll give you some overviews of the basics of Lisp.

Arithmetic

&gt; (+ 2 2)
4

This adds 2 and 2. Notice that Lisp arithmetic (and all Lisp functions) have prefix notation: the function name always comes first. You can nest values like the following:

&gt; (+ (+ 1 1) 1)
3

Printing

&gt; (format t "Hello, ~A~%" "Jacob")
"Hello, Jacob"
nil

format‘ is the function name. This is the Lisp-version of ‘printf‘,

The second argument is the destination stream. You can give this ‘t‘ or ‘nil‘ for true or false, or the name of a stream.

When ‘t‘ is given, the value is printed to Standard Output. When ‘nil‘ is given, the value is returned as a string.

The third argument is the formatting string. “~” is the escape character. “~A” means that it takes an argument that follows (like printf), and ~% is a newline.

There are other functions that you can use for printing, like ‘princ‘. I usually stick with ‘format‘, but there are different print semantics for different functions.

Defining functions

&gt; (defun adding-function (arg1 arg2)
    "Adds arg1 and arg2."
    (+ arg1 arg2))
ADDING-FUNCTION
 
&gt; (adding-function 1 2)
3
 
&gt; (+ (adding-function 1 2) 1)
4

Here we see a function definition and two function calls. Let’s examine the function definition:

&gt; (defun adding-function (arg1 arg2)

This can be considered the prototype line. ‘adding-function’ is the name of the function. It takes two mandatory parameters, ‘arg1′ and ‘arg2′, both with no default values.

"Adds arg1 and arg2."

This is the “documentation string.” A string may optionally be the first atom of a function, and it can be accessed from within Lisp using Lisp’s documentation reading abilities. Note that unlike wimpy strings in most languages, Lisp strings can contain newlines with no extra syntactical work.

(+ arg1 arg2))

This is the executed statement within the function body. A Lisp function returns the return value of the last statement. Since this is the only statement, it returns the addition of arg1 and arg2.

Defining variables

Defining a variable for the first time in SBCL:

(defvar my-var) ; my-var is 'nil'.
(defvar my-var 'a-value) ; my-var is 'a-value'.

Notice the quote in 'a-value. The single quotation mark indicates that the following expression is data, not code. Otherwise, it would try to look up the value of the variable a-value, which we may or may not have defined. Either way, it’s not what we want.

If a variable is already defined, you can use ‘setf‘:

&gt; (setf my-var 3)
3

Conditionals

For statements that only execute when something is true, use ‘when‘. For statements that only execute when something is false, use ‘unless‘.

&gt; (when (= 1 1)
    t)
t
&gt; (unless (= 1 1)
    t)
nil

For statements of the form “if (true), do (x), otherwise do (y)“, use ‘if‘.

&gt; (if expression
    x
    y)

If ‘expression‘ doesn’t evaluate to ‘nil‘, then ‘x‘ is executed and its return value is returned. Otherwise, ‘y‘ is executed and its return value is returned.

For statements involving a lot of if, else-if clauses in other languages, use cond:

(cond ((test1) (expression1))
      ((test2) (expression2))
      ; ...
      (t (default-expression)))

Iteration

The two easiest ways to iterate are the macros ‘dotimes‘ and ‘dolist‘.

&gt; (dotimes (i 3)
    (format t "~A" i)
012
nil

dotimes‘ is exactly as it sounds: it executes a statement a number of times. You assign a variable (in our case, ‘i‘) and tell it the number of times it shall execute, and the variable takes on the values of all of the integers in the range [0, n).

&gt; (dolist (i '(1 2 3))
    (format t "~A" i))
123
nil

dolist‘ iterates through a list much in the same way ‘dotimes‘ does.

Reduce

The idea of ‘reduce‘ is to iterate through a set, applying a function to each value that acts as an accumulator. For instance, we can do this with addition:

&gt; (reduce #'+ '(1 2 3))
6

Lambdas

If you want to define your own functions for ‘reduce‘ without writing formal functions, you can do them as a ‘lambda‘. That’s just a fancy word for ‘function with no name’. It consists of the name, the argument list, and a function body to execute:

&gt; (lambda (x) (+ x 2))

This defines an anonymous function that adds 2 to the input given. The only difference from ‘reduce‘ is that we need to provide two parameters: the accumulated value and the next value in the list.

You’re going to use this. A lot. Formally defining every function is not worth it. A lot of Lisp code ends up much cleaner with functional approaches.

To define our own addition function for ‘reduce‘:

&gt; (reduce (lambda (x y) (+ x y)) '(1 2 3))
6

Other features of Common Lisp

  • Macros: Creating code on-the-fly
  • CLOS: Common Lisp Object System. Lisp’s answer to Object Oriented programming.
  • Packages: This is how Lisp does namespacing.
  • More iteration constructs than you know what to do with.
  • mapcar‘: Apply a function to each element of a list
  • Hash tables
  • Arbitrary precision integers and numbers
  • cons: “Construct” function. This is the function that builds lists.car: Returns the first element of a list.
  • cdr: Returns the tail of a list (everything but the car).
  • Arbitrary binary manipulation
  • eval‘: Generate code from data at runtime.
  • File streams, input streams, output streams, stream redirections, oh my!
  • FFI: Foreign function interface. This lets you interface Lisp with C. You’ll probably need to do this if you want to add functionality to Common Lisp. It’s actually surprisingly easy to use.

Resources

Books

ANSI Common Lisp by Paul Graham. A great first Lisp book. It can be used as a textbook.

Paradigms of Artificial Intelligence Programming by Peter Norvig. The best programming book I have ever read. It does have quite a bit on AI, but it also has extensive sections on advanced Lisp programming.

Websites

SBCL: The Lisp implementation I currently use.

SLIME: A Lisp interaction plugin for Emacs.

Limp: A SBCL plugin for Vim.

cliki.net: A general Lisp resource. The home of all projects remotely installable using asdf-install.

Common Lisp Cookbook: An incomplete, yet still helpful, recipe book for Lisp code.

Popularity: 65% [?]

Reader Comments

Heh… you picked the one thing in C++ that does return a value.

cout << 1+3 is really a function call
ostream& operator<<(int) is its type signature. It returns the ostream reference so you can chain it in larger expressions.

You wrote a really good article. Useful stuff!

#1 
Written By tonetheman on December 29th, 2008 @ 9:25 am

Haha, good catch. I knew that it chained by returning a reference to the ostream, but that obviously wasn’t enough to stop me from making the mistake.

#2 
Written By Jake on December 29th, 2008 @ 9:36 am

You might want to try Cusp, an eclipse plug-in for Common Lisp.

http://www.bitfauna.com/projects/cusp/

#3 
Written By Joseph Gutierrez on December 29th, 2008 @ 11:00 am

Other stuff to get started:

clbuild, an easier way to get all those packages installed: http://common-lisp.net/project/clbuild/

ABLE, a all-in-one Lisp IDE that’s ideal for people trying lisp for the first time http://phil.nullable.eu/

“Casting SPELs in Lisp” – Cool tutorial http://www.lisperati.com/casting.html

– Dave.

#4 
Written By Dave on December 29th, 2008 @ 11:10 am

I (and I am sure a lot of other Lispers) would highly recommend “Practical Common Lisp” by Peter Seibel under Resources/Books.

The book is also available online: http://gigamonkeys.com/book/

#5 
Written By Chaitanya Gupta on December 29th, 2008 @ 12:52 pm

to Dave:

I still can’t run the Casting Spels tutorial in any Lisp implementation I download, I remember trying with Lisp in a box time ago, there was an error in the implementation…

http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2006-09/msg00483.html

today just for curiosity I downloaded SBCL and pasted the code of the tutorial:

http://www.lisperati.com/code.html

and got another set of errors…

I see why many newcomers are worried and lose the interest in the language when simple and *famous* lisp tutorials desn’t run out of the box in modern and updated lisp implementations, especially in the windows side.

#6 
Written By ex on December 29th, 2008 @ 1:50 pm

Nice tutorial, Jake. One minor point: elisp is not a subset of Common Lisp. The biggest difference I recall is that elisp variables have dynamic scope, so elisp doesn’t closures. There is an add-on package that emulates some of Common Lisp. One or two projects are out there (climacs, for one) to rewrite emacs in Common Lisp, but as far as I know they aren’t ready for serious use.

#7 
Written By Phil on December 29th, 2008 @ 8:32 pm

Nice overview, except: “subset of Common Lisp. Called ‘elisp’” — Emacs Lisp is not a subset of Common Lisp by any stretch of the imagination. :-)

#8 
Written By Tim on December 29th, 2008 @ 9:06 pm

Just to let you know: the SBCL + ASDF combo does not run on Windows without some major kluging. Also, SLIME has a bug dealing with paths with spaces in them, which are commonplace in Windows (eg. the default SBCL installation directory: “C:\Program Files\SBCL…”).

You may want to add “Linux” to the list of required software…

#9 
Written By Rob on December 30th, 2008 @ 2:53 am

One of the biggest hurdles for the beginner is getting something *done*. The interactive environment, and all its benefits, keeps them from doing just that. They can create toy fibonacci printers, but nothing that does work they way they are used to it.

I recommend clisp or gauche for those beginners. Slime (or vi-lisp) handles them just fine, and you can write scripts. They use the interactive environment, but they end up with a script that they can run separately and do real work with.

Next thing you know, the interactive environment clicks with them, and they can then choose their mode of development.

#10 
Written By jlbec on December 30th, 2008 @ 6:38 am

Any common lisp, emacs+lisp or schema emulations in JavaScript?

#11 
Written By Oleg on December 30th, 2008 @ 10:07 am

@Oleg: There’s ParenScript which compiles to Javascript:

http://common-lisp.net/project/parenscript/

Or for an interpreter:

http://joeganley.com/code/jslisp.html

Neither are Common Lisp or Scheme though.

#12 
Written By Matt Curtis on December 31st, 2008 @ 5:47 am

“Common Lisp Quick Reference” formatted for printing: http://clqr.berlios.de/

#13 
Written By Christian Mueller on January 8th, 2009 @ 1:11 pm

“You will want to use the REPL for most of your Lisp tasks, and this will only be bearable from within a good editor.”

Nonsense.

% rlwrap sbcl
* (require :sb-aclrepl)
CL-USER(1):

Then use ASDF to reload your system after editing it with whatever editor you want.

Make use of DESCRIBE/:DE, TRACE/:TR and Readline’s history C-r heavily.

Leslie

#14 
Written By Leslie P. Polzer on January 9th, 2009 @ 6:55 am

This is very helpful, thanks.

One minor nit, the emacs snippet for setting up slime has some HTML in the load path value. It’s got <em> in it. Since it’s an example value and has to be changed anyway, it’s a minor nit though.

#15 
Written By Seth Mason on January 9th, 2009 @ 5:16 pm

It would be really simple to add the superior theme just about this post with a help of submit article service, but very oft people opt for article writing submission. And I do not really know what should be the best.

#16 
Written By sLEllen on December 25th, 2009 @ 11:27 pm

Add a Comment

required, use real name
required, will not be published
optional, your blog address