# 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
``````