Search code examples
lisp

LISP appending item to array from a for loop


I'm trying to add an item to an array if this item is not already in the array. Essentially what I want to achieve is to iterate through a list remove any duplicates by checking if they already exist.

Here's how I've started:

(defun reduce(mylist)

    (setq newList (list ()) )
    (loop for item in mylist 
        do (


            (if (not (member item newList))


            )


        ))


)

(reduce '(3 4 5 4 5))

The error I'm getting is (IF (NOT (MEMBER 'ITEM 'NEWLIST))) should be a lambda expression. I know this is something to do with how item and newList are being accessed and can't figure out how to correct it.


Solution

  • The error is caused by wrapping the body of the do form with parentheses. Parens have meaning in lisp, so 'extra' wrapping like this will break the code.

    There are some other mistakes. setq is used to assign to an unbound variable. You should use let to establish a binding instead. The initial value of that variable is a one-length list containing (), while it should probably just be ().

    reduce is already a Common Lisp function, so a difference choice of name would be a good idea.

    Finally, the formatting isn't either idiomatic or consistent - you have mylist and newList. A lisp programmer would spell these names my-list and new-list.

    Here's how it might look when cleaned up a bit. I've left some important parts out for you to fill in.

    (defun unique-elements (list)
      (let ((result ()))
        (loop for item in list
              do (when (not (member item result))
                   ...))
        ...))
    

    (It would be cleaner to use loop's collection machinery for this job, but I decided an example of how to use do would be more helpful.)