Lisp:将 &rest 参数传递给宏
Lisp: Pass &rest parameters to a macro
我正在尝试构建一个函数来访问数据库中的记录:
(select :title "milk" :rating 7)
但是,它只是返回数据库中的所有记录。我相信这是因为我将 &rest
参数传递给宏并且它按字面解释参数名称 "fields"。我尝试从我的宏中删除 &rest
,但随后我收到关于未传递列表的错误。我试过在各个地方调用(列表字段)无济于事(在宏中,在调用宏的函数中,在宏调用的函数中)。
以下代码按预期工作:
(select-custom (where :title "milk" :rating 7))
并且 returns 仅匹配参数的记录。
源代码:
(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))
returns
(SELECT-CUSTOM (WHERE :TITLE "milk" :RATING 7))
我正在尝试构建一个函数来访问数据库中的记录:
(select :title "milk" :rating 7)
但是,它只是返回数据库中的所有记录。我相信这是因为我将 &rest
参数传递给宏并且它按字面解释参数名称 "fields"。我尝试从我的宏中删除 &rest
,但随后我收到关于未传递列表的错误。我试过在各个地方调用(列表字段)无济于事(在宏中,在调用宏的函数中,在宏调用的函数中)。
以下代码按预期工作:
(select-custom (where :title "milk" :rating 7))
并且 returns 仅匹配参数的记录。
源代码:
(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))
returns
(SELECT-CUSTOM (WHERE :TITLE "milk" :RATING 7))