This is my attempt to make a Common Lisp tutorial, since all of the ones I found on the internet were either out of date or needlessly confusing.
This is a guide that I made of information I wish I had when starting with Lisp. It does assume prior programming knowledge in another language. It's hardly comprehensive, but will hopefully be a good starting place for learning the language. Enjoy!
In Lisp, nearly everything is a function. Even the mathematical operators. For example:
(+ (* 2 3) 1)
As you can tell, the functions open and close with parenthesis. The format for calling functions in Lisp is
(function arg1 arg2)
setq is used to set variables.
(setq var 32) (setq str "Texas") (setq lst '(1 2 3))
The three types of data here are numbers, strings, and lists. Notice that Lisp, unlike Java, is dynamically typed.
' in list statement is called the quote operator, and tells Lisp that the input is a list, and not to interpret it as a function.
setq sets the variable globally. To create a local variable (e.g. inside a function), use the
(let ((a 1) (b 2)) ... )
b will only be defined within
To comment in Lisp, prefix the line with
; This is a comment!
if statement is a bit different from other programming languages.
(if (< 2 3) (... true ...) (... false ...))
Lisp executes the first block of code if the conditional statement is true. The second statement (which is optional) serves as the else statement.
If you want to execute multiple functions in the if statement (which is common) use the
progn function, which serves to group multiple functions together.
(if (> 3 4) (progn (setq x (+ x 1)) (setq y x)) (setq x 0))
If you want an if else statement, then you'd want to use the
(cond ((> x 1) (setq y 1)) ((< x 1) (setq y 2)) (t (setq y 0)))
For boolean values,
t represents true, and
nil represents false. Lisp treats an empty list
nil) as false and all other inputs as true.
This is a convenient feature of the language to know. For instance, to do something only if a list is not empty, the following two chunks of code are identical.
(if (> (length lst) 0) (...))
(if lst (...))
While loops are accomplished in the following manner:
(loop while (> n 0) (setq n (- n 1)))
Although for the most part, recursion is the more popular way to accomplish loops.
Lists are important in Lisp, which is why Lisp stands for LISt Processing. I'd recommend reading up on Wikipedia's article on linked lists to fully understand this section.
(setq lst '(1 2 3))
To get the first item from the list, use the
first function. To get the rest of the items, use
rest. The are historically known as
cdr, so you may see it referred to as such in older texts.
(first lst) => 1 (rest lst) => (2 3)
Lisp provides some helpful shortcuts to access other items in the list as well.
(second lst) => 2 (third lst) => 3 (fourth lst) => nil
Note: You could access these elements without these functions through repeatedly using
rest. For instance,
second is equivalent to
(first (rest lst))).
These functions are to save you a bit of typing.
To add an item to the beginning of the list, use the
cons returns a new list with the element prefixed to the beginning of the list.
(cons 0 lst) => (0 1 2 3)
These functions really only make sense in the context of recursion, which is very prevalent in Lisp. Below is an example of a recursive sum function which uses both
rest in a recursive context.
(defun sum (lst) (if (not lst) 0 (+ (first lst) (sum (rest lst)))))
defun is used to define functions.
(defun square (x) (* x x)) (defun add (x y) (+ x y))
Note: Lisp implicitly returns the value of the last statement in a function.
Calling functions is pretty straight forward; we've been doing it throughout this guide.
(square 9) => 81 (add 2 4) => 6
One of Lisp's most powerful features is the ability to pass functions to other functions. I'll list below some of the built in functions in Lisp that take advantage of this feature and are important to know. Most of these functions take two arguments, a function and a list.
mapcar(map). Returns the list the results from applying the function to each of the items in the list. The following example returns a new list with all the elements squared.
(mapcar 'square '(1 2 3 4 5)) => '(1 4 9 16 25)
remove-if(filter). Removes items from the list if the item, when plugged into the function, returns true. The following example returns a new list with all the odd numbers removed.
(remove-if 'oddp '(1 2 3 4 5)) => '(2 4)
Note: Built-in functions in Lisp that end in a 'p' are predicates and return a boolean value.
reduce. Reduces a list to a single value by applying the function to each of the items. The following example is equivalent to the sum function.
(reduce '+ '(1 2 3 4 5)) => 15
Writing your own function to take in a functions is not particularly hard. Below is an example of how you could implement your own
(defun my-mapcar (fn lst) (if lst (cons (funcall fn (first lst)) (my-mapcar fn (rest lst)))))
funcall is used to run functions that are stored in variables
It's occasionally useful (particularly with the higher-order functions listed above) to create a function without a name, typically because it is only getting used once.
For instance, say you wanted to double all the elements in a list. A function to double a number would rarely get used outside this call, so this is a good opportunity to create an anonymous function. The following two chunks of code are equivalent.
(defun double (x) (* x 2)) (mapcar 'double '(1 2 3 4 5)) => '(1 4 6 8 10)
(mapcar (lambda (x) (* x 2)) '(1 2 3 4 5)) => '(1 4 6 8 10)
It'll be a judgement call whether to go with the brevity of an anonymous function or the readability afforded by naming the function.
More complicated printing in Lisp is a bit difficult. Lisp has the
format function, which is analogous to the
printf function in C. The basic structure is
(format t "~a ~a of beer on the wall.~%" 99 "bottles")
t argument means to print to the standard output,
~a says to replace with the variable, and
~% means newline.
For a more in depth look at Lisp's
format function, refer to this chapter in Practical Common Lisp. It has everything you could possibly want to know and more about printing in Lisp.
by Max Timkovich (if you have any suggestions for improvements, shoot me an email)
last updated August 6, 2014