当我运行我的代码时,它说我的fill-lib函数中有一个未绑定的变量,但我不知道哪个变量是未绑定的或为什么。
(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)))))
答案 0 :(得分:2)
cond
special for具有抽象语法(cond (<test> [<form> ...])...)
。也就是说,每个&#34;声明&#34;或&#34;测试&#34;需要是一个列表,从测试表单开始。如果测试形式是非零的(对于&#34而言基本上是Common Lisp;真的&#34;),那么后续的形式将在一个隐含的预测中进行评估。 (基本上是&#34;代码块&#34;)。如果没有结果形式,则返回值将是测试表单的值。如果它是nil(Common Lisp for&#34; false&#34;),则以相同的方式评估下一个测试。
您有(cond (> count 1) (return (princ "Library filled")))
,这是一个cond
表单,其中包含两种表单,第一种是(> count 1)
,如果变量>
将被解释为&#34}是非零的,首先评估count
,然后评估1
并让最后的结果成为cond形式的结果&#34;。
如果你在这里使用when
代替cond
,那么(可能)会被清除,因为(when (> count 1) (return (princ "Library filled")))
会做我只能假设你想做的事(打印&#34;库已填充&#34;并从函数中返回该字符串。
答案 1 :(得分:1)
(defstruct book
(title nil)
(author nil)
(genre nil))
(setf b (make-book)) ; b is unbound
(setf lib ()) ; lib is unbound
(defun fill-lib ()
(setq count 1) ; count is unbound
(with-open-file (s-stream "/Users/David/Desktop/Books.txt"
:direction :input)
(loop
(cond (> count 1) (return (princ "Library filled"))) ; > is unbound, return is unbound
(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)))))
因此,您有5个位置用于处理未绑定的变量。
对于前三个:不要setf
未绑定的变量。使用defparameter
或
如果要引入全局特殊变量,则在顶级defvar
。
使用let
,let*
或multiple-value-bind
进行新的本地绑定(或函数)
参数,或do
循环......)。
对于另外两个:cond
将条件形式的子句作为第一个
元素和身体作为休息,所以它必须是:
(cond ((> count 1) (return (princ "Library filled"))))
对于只有一个子句的条件,请更好地使用when
:
(when (> count 1)
(return (princ "Library filled")))
改进代码:
(defstruct book
(title nil)
(author nil)
(genre nil))
(defvar *lib* ())
(defun fill-lib (filename count)
(with-open-file (s-stream filename
:direction :input)
(loop :repeat count
:for b := (make-book :title (read-line s-stream)
:author (read-line s-stream)
:genre (read-line s-stream))
:do (push b *lib*)))
(princ "Library filled."))