lispcommon-lispdifference-lists

To sort out atoms first and then sublists from a list in LISP


I have this homework in LISP where I need to sort out atoms and then sublists from a list. I'm sure this is supposed to be easy task but as I'm not much of a programmer then this is really taking quite a while for me to understand.

I have this list of numbers:

(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6)

And if I understand correctly my task then I should get something like this:

(5 -1 -6 (2 6 1) (8 7 -3) (0 (9 4)))

So far all I found out is how to count atoms and/or sublists but I don't need that.

(DEFUN ATOMNUMBER (L) (COND ((NULL L) 0)
  ((ATOM (CAR L)) (+ 1 (ATOMNUMBER (CDR L))))
  (T (ATOMNUMBER (CDR L))) ))

Also that function should work correctly even when there are only sublists, only atoms or just empty list.

Maybe someone can give me any examples?

Thanks in advance!


Solution

  • I am more used to Scheme but here's a solution that works in Lisp:

    (defun f (lst)
      (labels 
          ((loop (lst atoms lists)
             (cond
              ((null lst) 
               (append (reverse atoms) (reverse lists)))
              ((atom (car lst))
               (loop (cdr lst) (cons (car lst) atoms) lists))
              (T
               (loop (cdr lst) atoms (cons (car lst) lists))))))
        (loop lst '() '())))
    
    (f '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6))
    

    Basically you iterate over the list, and each element is either appended to the atoms list or the lists lists. In the end you join both to get your result.

    EDIT

    The remove-if version is way shorter, of course:

    (let ((l '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6)))
       (append
        (remove-if-not #'atom l)
        (remove-if     #'atom l)))