在Practical Common Lisp的第一个示例(数据库示例)中,作者使用了一个宏和几个支持函数来替换一个更大的函数,名为where
. 当where
是函数时,代码工作正常,但宏设置返回“未定义变量”和“未绑定变量”错误。(请注意,我注释掉了原始函数,重新启动了 Emacs 并在添加where
宏后重新编译了我的文件。)
根据示例,REPL 中捕获的样式警告对我来说是最可疑的,因为宏应该使用ROW
而不是评估。CD
为什么ROW
不用?如何解决此警告?
这打印在 REPL 中:
; in: SELECT (WHERE :TITLE "Animals" :RIPPED T)
; (WHERE :TITLE "Animals" :RIPPED T)
; ==>
; #'(LAMBDA (ROW)
; (AND (EQUAL (GETF CD :TITLE) "Animals") (EQUAL (GETF CD :RIPPED) T)))
;
; caught STYLE-WARNING:
; The variable ROW is defined but never used.
; in: SELECT (WHERE :TITLE "Animals" :RIPPED T)
; (WHERE :TITLE "Animals" :RIPPED T)
; --> FUNCTION AND IF EQUAL
; ==>
; (GETF CD :TITLE)
;
; caught WARNING:
; undefined variable: CD
;
; compilation unit finished
; Undefined variable:
; CD
; caught 1 WARNING condition
; caught 1 STYLE-WARNING condition
这打印在调试空间中:
The variable CD is unbound.
[Condition of type UNBOUND-VARIABLE]
以下是我的 .lisp 文件中的支持函数和宏:
; this function is used in both implementations. *db* is a (global) database
(defun select (selector-fn)
(remove-if-not selector-fn *db*))
(defun make-comparison-expr (field value)
`(equal (getf cd ,field) ,value))
(defun make-comparisons-list (fields)
(loop while fields
collecting (make-comparison-expr (pop fields) (pop fields))))
(defmacro where (&rest clauses)
`#'(lambda (row) (and ,@(make-comparisons-list clauses))))
我正在使用 SBCL、Emacs 和 Slime。