Stats

313 Contributors: 12 Monday, April 24, 2017
Licensed under: CC-BY-SA
Not affiliated with Stack Overflow
Rip Tutorial: riptutorial@gmail.com
Roadmap: roadmap

Getting started with common-lisp

Remarks

This is a simple hello world function in Common Lisp. Examples will print the text Hello, World! (without quotation marks; followed by a newline) to the standard output.

Common Lisp is a programming language that is largely used interactively using an interface known as a REPL. The REPL (Read Eval Print Loop) allows one to type code, have it evaluated (run) and see the results immediately. The prompt for the REPL (at which point one types the code to be run) is indicated by CL-USER>. Sometimes something other than CL-USER will appear before the > but this is still a REPL.

After the prompt comes some code, usually either a single word (i.e. a variable name) or a form (a list of words/forms enclosed between ( and )) (i.e. a function call or declaration, etc). On the next line will be any output that the program prints (or nothing if the program prints nothing) and then the values returned by evaluating the expression. Normally an expression returns one value but if it returns multiple values they appear once per line.

Versions

VersionRelease Date
Common Lisp1984-01-01
ANSI Common Lisp1994-01-01

Basic expressions

Let’s try some basic expression in the REPL:

CL-USER> (+ 1 2 3)
6
CL-USER> (- 3 1 1)
1
CL-USER> (- 3)
-3
CL-USER> (+ 5.3 (- 3 2) (* 2 2))
10.3
CL-USER> (concatenate 'string "Hello, " "World!")
"Hello, World!"
CL-USER> 

The basic building block of a Common Lisp program is the form. In these examples we have functions forms, that is expressions, written as list, in which the first element is an operator (or function) and the rest of the elements are the operands (this is called “Prefix Notation”, or “Polish Notation”). Writing forms in the REPL causes their evaluation. In the examples you can see simple expressions whose arguments are constant numbers, strings and symbols (in the case of 'string, which is the name of a type). You can also see that arithmetic operators can take any number of arguments.

It is important to note that parentheses are an integral part of the syntax, and cannot be used freely as in other programming languages. For instance the following is an error:

(+ 5 ((+ 2 4)))
> Error: Car of ((+ 2 4)) is not a function name or lambda-expression. ...

In Common Lisp forms can also be data, symbols, macro forms, special forms and lambda forms. They can be written to be evaluated, returning zero, one, or more values, or can be given in input to a macro, that transform them in other forms.

Common Lisp Learning Resources

Online Books

These are books that are freely accessible online.

Online References

Offline Books

These are books that you'll likely have to buy, or lend from a library.

Online Communities

Libraries

Pre-packaged Lisp Environments

These are Lisp editing environments that are easy to install and get started with because everything you need is pre-packaged and pre-configured.

  • Portacle is a portable and multiplatform Common Lisp environment. It ships a slightly customized Emacs with Slime, SBCL (a popular Common Lisp implementation), Quicklisp and Git. No installation needed, so it's a very quick and easy way to get going.
  • Lispbox is an IDE (Emacs + SLIME), Common Lisp environment (Clozure Common Lisp) and library manager (Quicklisp), pre-packaged as archives for Windows, Mac OSX and Linux. Descendant of "Lisp in a Box" Recommended in the Practical Common Lisp book.
  • Not pre-packed, but SLIME turns Emacs into a Common Lisp IDE, and has a user manual to help you get started. Requires a separate Common Lisp implementation.

Common Lisp Implementations

This section lists some common CL implementations and their manuals. Unless otherwise noted, these are free software implementations. See also the Cliki's list of free software Common Lisp Implementations, and Wikipedia's list of commercial Common Lisp Implementations.

Hello World

What follows is an excerpt from a REPL session with Common Lisp in which a "Hello, World!" function is defined and executed. See the remarks at the bottom of this page for a more thorough description of a REPL.

CL-USER> (defun hello ()
           (format t "Hello, World!~%"))
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> 

This defines the "function" of zero arguments named hello, which will write the string "Hello, World!" followed by a newline to standard output, and return NIL.

To define a function we write

(defun name (parameters...)
  code...)

In this case the function is called hello, takes no parameters and the code it runs is to do one function call. The returned value from a lisp function is the last bit of code in the function to run so hello returns whatever (format t "Hello, World!~%") returns.

In lisp to call a function one writes (function-name arguments...) where function-name is the name of the function and arguments... is the (space-separated) list of arguments to the call. There are some special cases which look like function calls but are not, for example, in the above code there is no defun function that gets called, it gets treated specially and defines a function instead.

At the second prompt of the REPL, after we have defined the hello function, we call it with no parameters by writing (hello). This in turn will call the format function with the parameters t and "Hello, World!~%". The format function produces formatted output based on the arguments which it is given (a bit like an advanced version of printf in C). The first argument tells it where to output to, with t meaning standard-output. The second argument tells it what to print (and how to interpret any extra parameters). The directive (special code in the second argument) ~% tells format to print a newline (i.e. on UNIX it might write \n and on windows \r\n). Format usually returns NIL (a bit like NULL in other languages).

After the second prompt we see that Hello, World has been printed and on the next line that the returned value was NIL.

Hello, Name

This is a slightly more advanced example that shows a few more features of common lisp. We start with a simple Hello, World! function and demonstrate some interactive development at the REPL. Note that any text from a semicolon, ;, to the rest of the line is a comment.

CL-USER> (defun hello ()
       (format t "Hello, World!~%")) ;We start as before
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> (defun hello-name (name) ;A function to say hello to anyone
       (format t "Hello, ~a~%" name)) ;~a prints the next argument to format
HELLO-NAME
CL-USER> (hello-name "Jack")
Hello, Jack
NIL
CL-USER> (hello-name "jack") ;doesn't capitalise names
Hello, jack
NIL
CL-USER> (defun hello-name (name) ;format has a feature to convert to title case
       (format t "Hello, ~:(~a~)~%" name)) ;anything between ~:( and ~) gets it
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello-name "jack")
Hello, Jack
NIL
CL-USER> (defun hello-name (name)
       (format t "Hello, ~:(~a~)!~%" name))
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello-name "jack") ;now this works
Hello, Jack!
NIL
CL-USER> (defun hello (&optional (name "world")) ;we can take an optional argument
       (hello-name name)) ;name defaults to "world"
WARNING: redefining COMMON-LISP-USER::HELLO in DEFUN
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> (hello "jack")
Hello, Jack!
NIL
CL-USER> (hello "john doe") ;note that this capitalises both names
Hello, John Doe!
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~a ~r" name number)) ;~r prints a number in English
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16) ;this doesn't quite work
Hello, Louis sixteen
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~:(~a ~:r~)!" name number)) ;~:r prints an ordinal
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16)
Hello, Louis Sixteenth!
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~:(~a ~@r~)!" name number)) ;~@r prints Roman numerals
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16)
Hello, Louis Xvi!
NIL
CL-USER> (defun hello-person (name &key (number)) ;capitalisation was wrong
       (format t "Hello, ~:(~a~) ~:@r!" name number))
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16) ;thats better
Hello, Louis XVI!
NIL
CL-USER> (hello-person "Louis") ;we get an error because NIL is not a number
Hello, Louis ; Evaluation aborted on #<SB-FORMAT:FORMAT-ERROR {1006641AB3}>.
CL-USER> (defun say-person (name &key (number 1 number-p)
                                      (title nil) (roman-number t))
       (let ((number (if number-p
                 (typecase number
                   (integer
                (format nil (if roman-number " ~:@r" " ~:(~:r~)") number))
                   (otherwise
                (format nil " ~:(~a~)" number)))
                 "")) ; here we define a variable called number
         (title (if title 
                (format nil "~:(~a~) " title)
                ""))) ; and here one called title
         (format nil "~a~:(~a~)~a" title name number))) ;we use them here

SAY-PERSON
CL-USER> (say-person "John") ;some examples
"John"
CL-USER> (say-person "john doe")
"John Doe"
CL-USER> (say-person "john doe" :number "JR")
"John Doe Jr"
CL-USER> (say-person "john doe" :number "Junior")
"John Doe Junior"
CL-USER> (say-person "john doe" :number 1)
"John Doe I"
CL-USER> (say-person "john doe" :number 1 :roman-number nil) ;this is wrong
"John Doe First"
CL-USER> (defun say-person (name &key (number 1 number-p)
                                      (title nil) (roman-number t))
       (let ((number (if number-p
                 (typecase number
                   (integer
                (format nil (if roman-number " ~:@r" " the ~:(~:r~)") number))
                   (otherwise
                (format nil " ~:(~a~)" number)))
                 ""))
         (title (if title 
                (format nil "~:(~a~) " title)
                "")))
         (format nil "~a~:(~a~)~a" title name number)))
WARNING: redefining COMMON-LISP-USER::SAY-PERSON in DEFUN
SAY-PERSON
CL-USER> (say-person "john doe" :number 1 :roman-number nil) ;thats better
"John Doe the First"
CL-USER> (say-person "louis" :title "king" :number 16 :roman-number nil)
"King Louis the Sixteenth"
CL-USER> (say-person "louis" :title "king" :number 16 :roman-number t)
"King Louis XVI"
CL-USER> (defun hello (&optional (name "World") &rest arguments) ;now we will just
       (apply #'hello-name name arguments)) ;pass all arguments to hello-name
WARNING: redefining COMMON-LISP-USER::HELLO in DEFUN
HELLO
CL-USER> (defun hello-name (name &rest arguments) ;which will now just use
       (format t "Hello, ~a!" (apply #'say-person name arguments))) ;say-person
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello "louis" :title "king" :number 16) ;this works now
Hello, King Louis XVI!
NIL
CL-USER>

This highlights some of the advanced features of Common Lisp's format function as well as some features like optional parameters and keyword arguments (e.g. :number). This also gives an example of interactive development at a REPL in common lisp.

Lambda Expressions and Anonymous Functions

An anonymous function can be defined without a name through a Lambda Expression. For defining these type of functions, the keyword lambda is used instead of the keyword defun. The following lines are all equivalent and define anonymous functions which output the sum of two numbers:

(lambda (x y) (+ x y))
(function (lambda (x y) (+ x y)))
#'(lambda (x y) (+ x y))

Their usefulness is noticeable when creating Lambda forms, i.e. a form that is a list where the first element is the lambda expression and the remaining elements are the anonymous function's arguments. Examples (online execution):

(print ((lambda (x y) (+ x y)) 1 2)) ; >> 3

(print (mapcar (lambda (x y) (+ x y)) '(1 2 3) '(2 -5 0))) ; >> (3 -3 3)

Sum of list of integers

(defun sum-list-integers (list)
    (reduce '+ list))

; 10
(sum-list-integers '(1 2 3 4))

; 55
(sum-list-integers '(1 2 3 4 5 6 7 8 9 10))

The simple Hello World program in REPL

Common Lisp REPL is an interactive environment. Every form written after the prompt is evaluated, and its value is afterwards printed as result of the evaluation. So the simplest possible “Hello, World!” program in Common Lisp is:

CL-USER> "Hello, World!"
"Hello, World!"
CL-USER>

What happens here is that a string costant is given in input to the REPL, it is evaluated and the result is printed. What can be seen from this example is that strings, like numbers, special symbols like NIL and T and a few other literals, are self-evaluating forms: that is they evaluate to themselves.