Для начала небольшой «бенчмарк», С без всех оптимизаций в 7406000 раз быстрее.
(defun main ()
(declare (optimize (speed 3)))
(let ((n 99999) (l '()) (sum 0))
(loop for i from 0 to n
do (setq l (append l (list i))))
(setq sum 0)
(loop for i from 0 to n
do (setq sum (+ sum (nth i l))))
(format t "~d~%" sum)))
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
long n = 99999, *l = NULL, count = 0, sum = 0;
for (long i = 0; i <= n; i++) {
l = realloc(l, (count + 1) * sizeof(long));
l[count++] = i;
}
for (long i = n; i >= 0; i--) sum += l[i];
printf("%ld\n", sum);
}
Для чего же нужны cons? В качестве универсального строительного блока, я считаю это одна из самых худших структур. Все ее преимущества заканчиваются на быстром добавлении в начало. Добавление в конец уже нежелательно, разрез в произвольном месте тоже, так как нету даже быстрого доступа к случайному элементу. Она медленная и неудобная, можно придумать кучу более быстрых и удобных структур. Даже JS на световые годы опережает Lisp со своим JSON, и его частое использование лишь подтверждает его удобство.
Так почему же cons из языка-ассемблера IPL 1956 года считается важным? Да, это неплохая структура для AST, если ваша машина имеет 16 кб памяти, но она распространилась по языку слишком широко.