Lists

Basics

Lists can be built using the list function:

CL-USER> (list 1 2 3)
(1 2 3)

You can use first, second, and all the way up to tenth to access the corresponding elements of a list:

CL-USER> (first (list 1 2 3))
1

CL-USER> (second (list 1 2 3))
2

These can also be used to set elements:

CL-USER> (defparameter my-list (list 1 2 3))
MY-LIST

CL-USER> (setf (second my-list) 7)
7

CL-USER> my-list
(1 7 3)

More generally, the nth function can be used:

CL-USER> (nth 1 (list 1 2 3))
2

And it works with setf:

CL-USER> (defparameter my-list (list 1 2 3))
MY-LIST

CL-USER> (setf (nth 1 my-list) 65)
65

CL-USER> my-list
(1 65 3)

Higher-Order Functions

Map

The map function takes a function and a list, goes through each element in the sequence, and returns a new list where every element is the result of calling that function with the original element.

For instance:

CL-USER> (mapcar #'evenp (list 1 2 3 4 5 6))
(NIL T NIL T NIL T)

Is equivalent to:

CL-USER> (list (evenp 1) (evenp 2) (evenp 3) (evenp 4) (evenp 5) (evenp 6))
(NIL T NIL T NIL T)

Another example:

CL-USER> (mapcar #'string-upcase (list "Hello" "world!"))
("HELLO" "WORLD!")

One way to help understand mapcar is by writing our own:

CL-USER> (defun my-map (function list)
           (if list
               (cons (funcall function (first list))
                     (my-map function  (rest list)))
               nil))
MY-MAP

CL-USER> (my-map #'string-upcase (list "a" "b" "c"))
("A" "B" "C")

Reduce

The reduce function can be used to turn a list into a scalar, by applying a function on successive subsets of the list. For instance:

CL-USER> (reduce #'+ (list 1 2 3))
6

You can also use a custom function:

CL-USER> (reduce #'(lambda (a b)
                     (* a b))
                 (list 10 20 30))
6000

The above is equivalent to (* 10 (* 20 (* 30))). To get a better understanding of how reduce works, we can use format:

CL-USER> (reduce #'(lambda (a b)
                     (format t "A: ~A, B: ~A~%" a b)
                     (* a b))
                 (list 1 2 3 4 5 6))
A: 1, B: 2
A: 2, B: 3
A: 6, B: 4
A: 24, B: 5
A: 120, B: 6
720

Sorting

The sort function allows you to sort a sequence:

CL-USER> (sort (list 9 2 4 7 3 0 8) #'<)
(0 2 3 4 7 8 9)

Destructuring

(defun destructure (list)
  (destructuring-bind (first second &rest others)
    list
    (format t "First: ~A~%" first)
    (format t "Second: ~A~%" second)
    (format t "Rest: ~A~%" others)))

This produces:

CL-USER> (destructure (list 1 2 3 4 5 6))
First: 1
Second: 2
Rest: (3 4 5 6)
NIL