Preface

This document is meant to be a primer for those who have read at least
one book on Common Lisp or Emacs Lisp, and are familiar with C. The
intent is to show how to solve various problems that the
aforementioned people may come across when attempting to learn Common
Lisp.

Cons cells and lists

The structure of cons cells and lists is covered well in the Emacs
Lisp Intro document that comes with Emacs, so I won't go into too much
detail on that end. We will instead give examples of the ways that
cons cells are used.

Basically, a cons cell is a singly-linked list item. The main
difference between cons cells and most linked-list implementations is
that there is no special class (different from the element class
itself) that contains a "head" variable. Every list element can be a
head, a tail, or even the very last element of a list (without the
delimiting NULL value), though doing the latter would not make the
result a proper list. Also, there is no limitation on the type of
things you can store in a cons cell — the requirement for the
contents of cons cells depends on the function you are passing one to.

Here are some examples of how cons cells are used to build lists.

Task 1: Iterate through a list and stop on a particular condition

The first example begins to walk through a list, but stops when some
condition is met. In particular, we stop when we find one number that
is not strictly greater than the one before it.

Task 2: Return a new list based on the given list

Another popular programmatical use of cons cells is to build a new
list from the contents of an old list. This can be either a "filter"
(something that preserves the order of the old list) or a "reverser"
(something that flips the order of the list).

The easiest way to build a new list is to start with the nil ending
symbol and build the list in reverse. Then if the original order of
the list is to be preserved, call nreverse on it to flip the order.
This is usually much better than building a list front-first, because
then you would have to traverse the entire contents of the new list
every time you want to add an item to it.

We use dolist here because it walks through the original list for us,
assigning each value of the list to item, and then calling setf.
Since we don't plan on stopping early, we can use dolist with
impunity. Here's what it would look like if we did not use dolist.

Now we give an example of turning a list of symbols into a list of
strings, where each string is the name of the corresponding symbol.
Note that if the user gives us a list of something other than symbols,
the call to symbol-value will throw an error.

Here, the mapcar function calls its first argument (which must be a
function) on every item in the second argument (which must be a list).
It collects the results from each function call and returns them as a
list.

(defunmy-symbol-to-string (list)
(mapcar #'symbol-name
list))

Here is a version of that example that does not use mapcar.

(defunmy-symbol-to-string (list)
(let ((newlist nil)
(current list))
(while current
(setf newlist (cons (symbol-name (car current))
newlist))
(setf current (cdr current)))
;; we built the list in reverse order, so reverse it again to get
;; it in the correct order
(nreverse newlist)))

The next example is more sophisticated, because instead of allowing an
error to be thrown, it uses "INVALID". This is handy when you're just
displaying a list instead of re-using it later on. Instead of passing
the name of the function symbol-name to mapcar, we will pass a
function that is created on-the-fly. The #' construct is a tip to the
Lisp compiler to tell it that what follows is a function — it isn't
strictly necessary, but it is good practice.

Most types have a predicate (that is, something that tests to
see whether the argument is something of that type) called TYPEp or
TYPE-p, where TYPE is the name of the type. Sometimes a "?"
character may be used instead of "-p", such as TYPE? in the variant
of Lisp called Scheme. Looking back to our first example, you can
see that we made a predicate function. I used the "?" notation
there because it feels more modern.

Compiling and executing Lisp programs

Once you start making entire programs or small scripts in Lisp, you
may wish to compile your code and run it from the command line, rather
than manually running it from a Lisp interpreter.

Generalized solution

For a more general solution, check out the cl-launch package. It
enables you to make shell scripts that run Lisp programs and provides
advice on what to put in Makefiles.

CLISP

If you're using the CLISP Common Lisp environment, the following
applies.

To compile a program named test.lisp program into a bytecode file
named test.fas, do the following.

clisp -c test.lisp

If you want less output to be shown, do the following instead.

clisp -q -c test.lisp

To run the compiled (or even uncompiled, if you skip the above step)
Lisp file, do the following, assuming that your entry function is
named main. Normally the result of the main function is shown when
it's done, but the (quit) command prevents that. The -on-error abort
option prevents clisp from dropping into a debugging prompt, and exits
instead when there is an error.