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