我正在尝试实现一个宏,它将无限的三元组参数列表扩展为lambda函数以检查参数(对象)。
e.g。
(where >= amount 5 equalp name "george")
=>
#'(lambda (arg)
(and
(>= (amount arg) 5)
(equalp (name arg) "george")))
我对这个宏定义非常接近:
(defmacro where (&rest list-of-argument-triplets )
`#'(lambda (arg)
(and
,(do ( (counter 0 (+ counter 3)) (liste (list)))
( (>= counter (list-length list.of-argument-triplets)) liste)
(push `( ,(nth counter list-of-argument-triplets)
( ,(nth (+ counter 1) list-of-argument-triplets) arg)
,(nth (+ counter 2) list-of-argument-triplets)
liste)))))
但这会扩展到
#'(lambda (arg)
(and ((>= (amount arg) 5)
(equalp (name arg) "george"))))
这是“和”之后的一个括号。作为结论,我必须在结果表单前面使用@,然后处理“@list” 好像它是一个参数名,因此我得到一个无值错误,而不是扩展列表。
*** - RETURN-FROM: variable @LISTE has no value
我该如何解决?
答案 0 :(得分:1)
代码气味:您使用NTH访问列表中的元素。
我首先要定义一个辅助函数,它从平面列表中得出三个元素列表的列表:
(defun triplets (list)
(loop while list
collect (list (pop list)
(pop list)
(pop list))))
CL-USER 1 > (triplets '(a b c d e f g h i))
((A B C) (D E F) (G H I))
然后编写宏稍微简单:
(defmacro where (&rest flat-triplets)
`#'(lambda (arg)
(and
,@(mapcar (lambda (triplet)
(destructuring-bind (fn accessor item)
triplet
`(,fn (,accessor arg) ,item)))
(triplets flat-triplets))))
CL-USER 2 > (macroexpand-1 '(where >= amount 5 equalp name "george"))
(FUNCTION (LAMBDA (ARG) (AND (>= (AMOUNT ARG) 5) (EQUALP (NAME ARG) "george"))))
T