João Costa
João Costa

Reputation: 33

Illegal syntax error

(defun copy (l)                                                                                                                         
  (let ((lst (list)))                                                                                                                   
    (loop for i in l                                                                                                                    
          (if (not (null i))                                                                                                   
              (push i (cdr (last lst))))))                                                                                     
  lst)                                                                                                                                  

I'm having an error which I don't understand.

This function is supposed to copy the elements of a list to a new list. The error apoints to illegal syntax inside the LOOP statement.

Upvotes: 1

Views: 396

Answers (1)

coredump
coredump

Reputation: 38789

What you are doing essentially boils down to the following piece of modern poetry:

(defun remove-nil (list) (remove nil list))

Your code is written as-if it was Scheme, which is quite different from Common lisp. In your case, this even makes your code errorneous. Details follow:

  1. The function is badly named, at first sight it looks like you only want to perform a copy but you are also filtering it.
  2. You can write list, there is no need to drop vowels.
  3. You don't need to write (list) to build an empty list, simply declaring the auxiliary variable without a binding will initialize it to nil. If you want, you can explicitely bind your variable to nil to notify readers that you are doing this on purpose, but I rarely see it.
  4. Let is not like Scheme's define, lst is not bound anymore when you escape the let. You should have this instead:

    (let ((lst ...))
       ...
      lst)
    
  5. (not (null x)) is the Scheme way of dealing with empty lists. In Common Lisp, you can write (when x ...).

  6. The loop macro allows two different forms, a simple one which looks like a progn (i.e. a list of forms) and another one where you use loop keywords (collect, sum, repeat, ...): your (if ...) would need to have a do before it. But you could also use the when loop keyword. This is what I would suggest to do if you want to use a loop:

    (defun remove-nil (list)
      (loop for e in list when e collect e))
    

Upvotes: 2

Related Questions