I am working on a recursive function that looks for the first odd number in a list. It works as expected.
But when there is NO odd number in a list, it returns an error. Id like to control this error with some sort of message that says "no odd values found".
(defun find-first-odd (x)
(cond ((oddp (first x)) (first x))
(t (find-first-odd (rest x)))))
(find-first-odd '(2 2 10 3 4 6 4)) ; => 3
(find-first-odd '(2 2 10 4 6 4)) ;=> value nil is not an integer
(find-first-odd '(2 2 10 4 6 4 . 2)) ;=> 2 is not type list
You need to test for the list being empty and do the appropriate thing. In general any function which searches a list recursively needs a termination test, and thus looks something like:
(defun search-list-for (l ...)
(cond ((null l)
...)
(<(first l) is what we're after>
...)
(t
(search-list-for (rest l) ...))))
and in this case:
(defun find-first-odd (l)
(cond
((null l)
nil) ;or whatever
((oddp (first l))
(first l))
(t
(find-first-odd (rest l)))))
You are lucky that, for your particular function, while (first '())
is perfectly legal in CL, it is not a number and so you get an error. In general you'll get failure to terminate:
(defun contains-thing-p/broken (l thing)
(cond
((eql (first l) thing)
t)
(t
(contains-thing-p/broken (rest l) thing))))
will not terminate if thing
is not in the list, and must be written using the above skeleton instead:
(defun contains-thing-p (l thing)
(cond
((null l)
nil)
((eql (first l) thing)
t)
(t
(contains-thing-p (rest l) thing))))