I am learning Lisp and have a problem where I have to remove all the numbers from a list, which also has nested lists. For example:
(REMOVE-NUM '(2 A (3 B) C D))
will output:
(A (B) C D)
I am not allowed to use loop
, if
, or mapcan
. I am to use basic operators and cond
statements. This is my current code:
(defun REMOVE-NUM (L)
(cond
((null L) nil)
((numberp (car L)) (REMOVE-NUM (cdr L)))
(t (cons (car L) (REMOVE-NUM (cdr L))))
)
My current code can remove the numeric atoms without nested lists, but once nested lists are involved, it lists out the nested list, without actually processing it. I know that this is an issue with my logic behind the recursion, but I for some reason cannot see it. My instinct is to change the last line to:
(t (cons (REMOVE-NUM (car L) (REMOVE-NUM (cdr L))))
another recursive call in the last line, but doing so gives an error because it tries to take car of an atom and pass it as a list to my function which can only take lists. I thought of maybe changing the base cases, but I can't think of a way to do so since numberp has to be condition used. Where is my recursion going wrong/what is it missing?
Isn't it obvious? Separate atom
(which could be unified with the null
case actually) and the listp
(which could then be simply t
) cases. You'll need to accept that your input isn't necessarily a list if you want recursion all the way, or else you need to peek at the cdr
and make sure it's listp
before you recurse. Throw in a cons
or two in your test case.
(REMOVE-NUM '(2 A (3 B) C (D . 7) (8 . E) F))
If you don't need to handle cons
cells in your lists, simply
(defun REMOVE-NUM (L)
(cond
((atom L) L)
((numberp (car L)) (REMOVE-NUM (cdr L)))
(t (cons (REMOVE-NUM (car L))
(REMOVE-NUM (cdr L)) ))))