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))

宏是在编译时展开的,它们不能使用运行时变量。