I don't think Common Lisp has an emphasis on recursion. As evidence, consider that it doesn't in the standard require any kind of tail recursion optimization and has multiple ways of doing iteration. Scheme is the language with the fetish about doing things with recursion.
Common lisp let's you do recursion when you need it and not when you don't. Using recursion for iterating through a list is stupid because you bury the lead in the middle of a function and you do the same thing until you stop. Using recursion for a tree or more connected graphs isn't because they are fundamentally recursive.
Sure, the issue is that most loops are farily simple and putting the logic in the middle of a function far away from the iteration is bad.
It's the same reason why I use let instead of a function when I want to encapsulate simple state across multiple statements. Sure they are both the same fundamentally, but one is much easier to reason about.
This is actually the core of what I was getting at. The way Lisp lists are constructed and processed actually encourages recursive methods.
But, again, it's probably because I've been exposed to too much Scheme that this sits so prominently in my mind. I've never worked in a large scale Common Lisp code base.
Lisp has imperative loops which process lists: prog/go, do, dolist, loop for in/on.
Then it has a bunch of higher order functions: mapcar, map, mapc, member, find, remove, delete, every, some, ...
For example this is the equivalent of an early 1960s procedure to map a function over a list for side-effects:
CL-USER 5 > (defun mapc-old (x f)
(prog ((m x))
loop
(when (null m) (return nil))
(funcall f (car m))
(pop m)
(go loop)))
MAPC-OLD
As you can see above, the above uses a PROG providing a local variable M, a tag LOOP, and is using a GO statement to pass control to the position of the LOOP tag.
We can then process a list. Here we print the squares of the elements.
Code using imperative loops to implement higher-order functions were common then. Then with macros one is hiding an imperative loop implementation behind a macro transformer: here the DOLIST macro
CL-USER 12 > (dolist (e '(1 2 3 4))
(print (expt e 2)))
1
4
9
16
NIL
Then one invented complex iteration sub-languages, here the LOOP macro in a tiny example.
CL-USER 17 > (loop for e in '(1 2 3 4)
do (print (expt e 2)))
1
4
9
16
NIL
Any list processing function, which is threatening to create stack overflows (even though some implementations can increase a stack at an stackoverflow error), is best rewritten into a function which does not cause stack overflows. Lisp uses traditionally imperative loop constructs for that. Scheme often uses tail-recursive functions for that.
Not really. You don't want to recurse down the tail of a list, as in practice that's a great way to overflow the stack.
In practice, you want to recurse only on the elements of a list. And that's just how you'd handle a tree whose nodes are vectors instead of lists. So the implication that lists lead to recursion is a red herring.
Scheme is misleading because of its fetish of implementing iteration with tail calls.
Btw - Racket guarantees more than Scheme.
In Racket non-tail calls can't lead to a stackoverflow.
When a "potential stackoverflow" is detected the "frames" are moved to heap,
and the computation continues.
> Not really. You don't want to recurse down the tail of a list, as in practice that's a great way to overflow the stack.
The SICP book had a paragraph on the distinction before recursive process and recursive procedure. I can't remember which was which, but the point there was that recursive procedure could be an iterative process if it's written with tail recursion in mind, in which case it would not overflow the stack.