Macros Lisp:Pass&;宏的rest参数
我正在尝试构建一个函数来访问数据库中的记录,如下所示:Macros Lisp:Pass&;宏的rest参数,macros,lisp,common-lisp,Macros,Lisp,Common Lisp,我正在尝试构建一个函数来访问数据库中的记录,如下所示: (select :title "milk" :rating 7) 但是,它只是返回数据库中的所有记录。我认为这是因为我正在将&rest参数传递给宏,而宏正在逐字解释参数名“fields”。我已尝试从宏中删除&rest,但随后出现了一个关于不传递列表的错误。我尝试在不同的地方调用(列表字段),但都没有用(在宏中,在调用宏的函数中,在宏调用的函数中) 以下代码按预期工作: (select-custom (where :title "milk"
(select :title "milk" :rating 7)
但是,它只是返回数据库中的所有记录。我认为这是因为我正在将&rest
参数传递给宏,而宏正在逐字解释参数名“fields”。我已尝试从宏中删除&rest
,但随后出现了一个关于不传递列表的错误。我尝试在不同的地方调用(列表字段),但都没有用(在宏中,在调用宏的函数中,在宏调用的函数中)
以下代码按预期工作:
(select-custom (where :title "milk" :rating 7))
并仅返回与参数匹配的记录
源代码:
(defun select (&rest fields)
(select-custom (where fields)))
(defun select-custom (selector-function)
(remove-if-not selector-function *db*))
(defmacro where (&rest fields)
`#'(lambda (cd) (and ,@(make-comparison-list fields))))
(defun make-comparison-list (fields)
(loop while fields
collecting (make-comparison-exp (pop fields) (pop fields))))
(defun make-comparison-exp (field value)
`(equal (getf cd ,field) ,value))
最好的解决方案是创建
where
的函数版本。但作为一个简单的拼凑,您可以使用eval
(defun select (&rest fields)
(select-custom (eval `(where ,@fields))))
您可以将
select
改为宏
(defmacro select (&rest fields)
`(select-custom (where ,@fields)))
你可以查一下
(macroexpand-1 '(select :title "milk" :rating 7))
返回
(SELECT-CUSTOM (WHERE :TITLE "milk" :RATING 7))
宏是在编译时展开的,它们不能使用运行时变量。