LISP: Multilevel Recursive Inverse Function
How can I change the list so that each sub-list is also reversed? This is what I have so far:
(defun REV (L)
(cond
((null L) nil)
((listp L)
(append
(REV (cdr L))
(list (car L))))
(t
(append
(REV (cdr L))
(list (car L))))))
You are on the right track, but your last two conditions have the same action, which should indicate that one of them is not doing what it should. Indeed, the second condition, case listp
, is not true, because when it is a list, you need to add back that list instead of the unmodified list. Possible Solution:
(defun reverse (l)
(cond ((null? l) nil)
((listp (car l)) (append (reverse (cdr l))
(list (reverse (car l)))))
(t
(append (reverse (cdr l))
(list (car l))))))
> (reverse '((1 2 3) (4 5 6)))
((6 5 4) (3 2 1))
As you can see, the only difference is that you are checking if the first item is a list, and if so, you change the first item before adding it.
I would write like this:
(defun reverse-all (list)
(loop
with result = nil
for element in list
if (listp element)
do (push (reverse-all element) result)
else do (push element result)
finally (return result)))
Sounds like a home problem :)
It looks like you started by writing the usual reverse code. I'll give you a hint: the second condition (listp L) is not entirely correct (it will always be true). You want to check if there is something else in the list.
dmitry_vk's answer (which is probably faster in most lisps than using append in the previous examples) in a more logical way:
(defun reverse-all (list)
(let ((result nil))
(dolist (element list result)
(if (listp element)
(push (reverse-all element) result)
(push element result)))))
Or even:
(defun reverse-all (list)
(let ((result nil))
(dolist (element list result)
(push
(if (listp element) (reverse-all element) element)
result))))