Jonath P
Jonath P

Reputation: 561

Flattening lists (while removing 'nil' and keeping atoms after " . ") in lisp

I want to create a function that would flatten a list and remove all potential nil inside.

Expected behavior, example 1:

(myfunc '(a (b (c) (d)) (e f) (g (h)) nil)) => (a b c d e f g h)

Expected behavior, example 2:

(myfunc '(a . d)) => (a d) 

my function so far:

(defun myfunc (l)
   (cond
      ((atom l) nil)
         ((and (atom (car l)) (not (equal (car l) nil))) (cons (car l) (myfunc (cdr l))))
         (t (append (myfunc (car l)) (myfunc (cdr l))))))

My function works as expected for the first example, but not the second. I get:

(myfunc '(a . d)) => (a) 
  1. Why doesn't it keep that d?

  2. Is there a way to fix it?

Upvotes: 1

Views: 814

Answers (1)

C. K. Young
C. K. Young

Reputation: 222973

Perhaps you should think about what the flatten function should do, in plain English:

  1. Base case: If flattening nil, return an empty list.
  2. Base case: If flattening single atoms, return a list containing just that.
  3. Recursive case: If flattening pairs, return a list appending the flattening of its car with the flattening of its cdr.

Here's how I'd implement the description I just gave:

(defun flatten (x)
  (cond ((null x) x)
        ((atom x) (list x))
        (t (nconc (flatten (car x)) (flatten (cdr x))))))

Upvotes: 2

Related Questions