Нет, это не хвостовая рекурсия. Ни ANSI Common Lisp ничего не говорит об этом, ни ваш код:
(defun collect (func args num)
(if (= 0 num)
()
(cons (apply func args)
(collect func args (- num 1)))))
Если вы посмотрите на свой код, вокруг вашего вызова COLLECT есть CONS. Этот CONS получает значение рекурсивного вызова COLLECT. Так что COLLECT не может быть хвостовой рекурсивной. Относительно просто переписать вашу функцию во что-то, что выглядит рекурсивно, введя переменную-аккумулятор. В литературе по Лиспу или Схеме это должно быть описано.
В Common Lisp стандартным способом программирования итерационных вычислений является использование одной из нескольких итерационных конструкций: DO, DOTIMES, DOLIST, LOOP, MAP, MAPCAR, ...
Стандарт Common Lisp не предусматривает оптимизацию оконечного вызова (TCO). Необходимо указать, что должен делать TCO при наличии нескольких других языковых функций. Например, динамическое связывание и специальные переменные влияют на TCO. Но стандарт Common Lisp просто ничего не говорит о TCO в целом и о возможных последствиях TCO. TCO не является частью стандарта ANSI Common Lisp.
Несколько реализаций Common Lisp имеют способ включить различные оптимизации хвостовых вызовов с помощью переключателей компилятора. Обратите внимание, что как способ их включения, так и ограничения зависят от конкретной реализации.
Резюме : В Common Lisp используйте итерационные конструкции, а не рекурсию.
(defun collect (func args num)
(loop repeat num
collect (apply #'func args)))
Добавлен бонус: его легче читать.