When I run my code it says that there is an unbound variable in my fill-lib function, but I have no clue what variable is unbound or why.
(defstruct book
(title nil)
(author nil)
(genre nil))
(setf b (make-book))
(setf lib ())
(defun fill-lib ()
(setq count 1)
(with-open-file (s-stream "/Users/David/Desktop/Books.txt"
:direction :input)
(loop
(cond (> count 1) (return (princ "Library filled")))
(setf b (make-book))
(setf (book-title b) (read-line s-stream))
(setf (book-author b) (read-line s-stream))
(setf (book-genre b) (read-line s-stream))
(setf lib (cons b lib))
(setq count (+ count 1)))))
The
cond
special for has the abstract syntax(cond (<test> [<form> ...])...)
. That is, each "statement" or "test" needs to be a list, starting with a test form. If the test form is non-nil (that's essentially Common Lisp for "true"), the consequent forms are evaluated in an "implicit progn" (basically "code block"). If there are no consequent forms, the return value would be the value of the test form. If it is nil (Common Lisp for "false"), the next test is evaluated in the same manner.You have
(cond (> count 1) (return (princ "Library filled")))
, this is acond
form with two forms, the first being(> count 1)
, which will be interpreted as "if the variable>
is non-nil, first evaluatecount
, then evaluate1
and let the result of that last be the result of the cond form".It would (probably) be cleared if you used
when
instead ofcond
here, since(when (> count 1) (return (princ "Library filled")))
would do what I can only assume you want to do (print "Library filled" and return that string from the function).So, you have 5 locations where you are working with unbound variables.
For the first three: do not
setf
unbound variables. Usedefparameter
ordefvar
at the top level, if you want to introduce a globally special variable. Uselet
,let*
, ormultiple-value-bind
for new local bindings (or function parameters, ordo
loops ...).For the other two:
cond
takes clauses that have a condition form as first element and a body as rest, so it would have to be:For conditionals with only one clause better use
when
:Improved code: