The main problem in the loop is the WHEN-expression. There are two ways you can write that:
Use the loop WHEN condition DO forms-clause:
(loop for...
when (eq ...) do (return-from ...))
Use the regular WHEN-macro inside a loop DO-clause:
(loop for...
do (when (eq ...)
(return-from ...)))
There are a few other things to fix in your code.
- When naming things in Lisp, use dashes between words rather than camelCase (
check-zero rather than checkZero).
- Use
= for general numeric comparison, or ZEROP to check that a number is zero. EQ is used to check if two objects are the same object.
- You can return from a loop using
RETURN
- I'm not quite sure what you're trying to accomplish with the
(VALUES-LIST (NTH ... (CAR ...))), but it's not going to work. If you're trying to simply loop over a flat list of values (such as (1 2 3 4 5 6)), you should be using the loop FOR item IN list-clause.
So now you should have something like:
(defun check-zero (list)
(loop for item in list
when (zerop item) do (return t)))
LOOP also has a THEREIS condition-clause that you could use:
(defun check-zero (list)
(loop for item in list
thereis (zerop item)))
This return as soon as it finds an item that satisfies ZEROP. However, there are easier ways to achieve the same. You could use MEMBER to check if the list contains a zero:
(defun check-zero (list)
(member 0 list :test #'=))
CL-USER> (check-zero '(1 3 4 3 5 7))
NIL
CL-USER> (check-zero '(1 3 4 3 0 5 7))
(0 5 7)
This returns a generalized boolean. That is, any value that is not NIL is considered true in Common Lisp.
Since there is a predicate function (ZEROP) to check if an object is a zero, you could also use SOME or MEMBER-IF for this:
(some #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> T
(member-if #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> (0 45 6 7)
(when (eq ...) (return-from...))so to havewhen (eq ...) (return-from...)and put adobefore(return-from...). - Renzo