3 ms·
> actually encourages recursive methods Not really. Lisp has imperative loops which process lists: prog/go, do, dolist, loop for in/on. Then it has a bunch o
by lispm 3y ago
> actually encourages recursive methods
Not really.
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.
CL-USER 6 > (mapc-old '(1 2 3 4)
(lambda (e)
(print (expt e 2))))
1
4
9
16
NIL
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.