Lists based on cons cells avoid heap fragmentation: all allocations are of the same size. This is not true of vectors.
Making different lists that share the same tail, by building at the front, is incredibly common in code that manipulates code.
For instance, in many situations you have a body of forms that are to be put into some statement:
(defun glue-args-and-body-making-lambda (args body)
`(lambda ,args ,@body))
That lambda expression shares the args object with the caller, of course (and an array would do the same), but it also shares the body object, which an array won't do unless it's a very specialized array.
The backquote expression can compile down to:
(list* 'lambda args body)
which allocates exactly two cons cells: one cell to hold lambda in its
car; another one to hold args in its
car and the body goes into the
cdr of that same one.
It's also incredibly common to work with the suffix of a list.
In the reverse direction, we can break the lambda:
(defun take-apart-lambda (lambda-expr)
(destructuring-bind (lambda-sym args &rest body) lambda-expr
(values args body)))
This requires no memory allocation We can pull the args out of an array-based lambda expression for free; but not the body (suffix of the array).
Vectors have the advantage of compact storage; a large vector's storage should be roughly the value word size times number of elements, plus small fixed overhead. Each element of a list costs us a cons cell (unless we have cdr coding, which is just little vectors in disguise). Cons cells can be compactly allocated, but not like the elements of a vector. They can be individually reclaimed though. If we cdr three steps down a list, and nothing has retained the pointer to that list, those three conses can be identified as garbage and reclaimed.