如何评估宏中 lambda 中的表单?
How do I evaluate form inside lambda that is within a macro?
我在使用以下宏时遇到问题:
(defmacro gather-params (&rest body)
"Return plist of params"
`(concatenate 'list
(map 'list
#'(lambda (plist)
(if (typep (first plist) 'keyword)
(cons 'list plist)
plist))
',body)))
在宏中,我无法通过在其前面添加逗号来使 plist 求值,例如:,plist 当我这样做时,编译器会抱怨变量 ,plist 不存在。
关于宏中的范围,我有什么不明白的地方吗?
当前结果:
input: (gather-params (:mykey (+ 1 1)) (list 1 2 3))
result: ((LIST :MYKEY (+ 1 1)) (LIST 1 2 3))
想要的结果:
input: (gather-params (:mykey (+ 1 1)) (list 1 2 3))
result: ((LIST :MYKEY 2) (LIST 1 2 3))
(concatenate 'list '(1 2 3))
就是 (copy-list '(1 2 3))
-> 两者的计算结果都是 (1 2 3)
.
宏生成代码。它有一个反引号列表。这个反引号列表是在宏扩展时计算的 -> 当宏扩展发生时,例如在编译期间。
生成的代码有一个带有参数的函数,名为 plist
。该函数在运行时执行。它在宏展开期间不存在。因此 plist
在宏展开期间没有变量。因此,在宏展开期间,您无法计算 plist
的值,因为那时该变量不存在。
如果你想评估代码,那么 Common Lisp 有函数 eval
。例如,可以在运行时调用 eval
。
CL-USER 31 > (defmacro gather-params (&rest body)
"Return plist of params"
`(map 'list
#'(lambda (plist)
(if (typep (first plist) 'keyword)
(list 'list
(first plist)
(eval (second plist)))
plist))
',body))
GATHER-PARAMS
CL-USER 32 > (gather-params (:mykey (+ 1 1)) (list 1 2 3))
((LIST :MYKEY 2) (LIST 1 2 3))
查看此示例,使用不同的方法:
CL-USER 42 > (defmacro gather-params (&rest body)
"Return plist of params"
`(list ,@(mapcar
(lambda (plist)
(if (typep (first plist) 'keyword)
(list 'list
''list
(first plist)
(second plist))
plist))
body)))
GATHER-PARAMS
CL-USER 43 > (let ((foo 1))
(gather-params (:mykey (+ foo foo)) (list 1 2 3)))
((LIST :MYKEY 2) (1 2 3))
我在使用以下宏时遇到问题:
(defmacro gather-params (&rest body)
"Return plist of params"
`(concatenate 'list
(map 'list
#'(lambda (plist)
(if (typep (first plist) 'keyword)
(cons 'list plist)
plist))
',body)))
在宏中,我无法通过在其前面添加逗号来使 plist 求值,例如:,plist 当我这样做时,编译器会抱怨变量 ,plist 不存在。
关于宏中的范围,我有什么不明白的地方吗?
当前结果:
input: (gather-params (:mykey (+ 1 1)) (list 1 2 3))
result: ((LIST :MYKEY (+ 1 1)) (LIST 1 2 3))
想要的结果:
input: (gather-params (:mykey (+ 1 1)) (list 1 2 3))
result: ((LIST :MYKEY 2) (LIST 1 2 3))
(concatenate 'list '(1 2 3))
就是 (copy-list '(1 2 3))
-> 两者的计算结果都是 (1 2 3)
.
宏生成代码。它有一个反引号列表。这个反引号列表是在宏扩展时计算的 -> 当宏扩展发生时,例如在编译期间。
生成的代码有一个带有参数的函数,名为 plist
。该函数在运行时执行。它在宏展开期间不存在。因此 plist
在宏展开期间没有变量。因此,在宏展开期间,您无法计算 plist
的值,因为那时该变量不存在。
如果你想评估代码,那么 Common Lisp 有函数 eval
。例如,可以在运行时调用 eval
。
CL-USER 31 > (defmacro gather-params (&rest body)
"Return plist of params"
`(map 'list
#'(lambda (plist)
(if (typep (first plist) 'keyword)
(list 'list
(first plist)
(eval (second plist)))
plist))
',body))
GATHER-PARAMS
CL-USER 32 > (gather-params (:mykey (+ 1 1)) (list 1 2 3))
((LIST :MYKEY 2) (LIST 1 2 3))
查看此示例,使用不同的方法:
CL-USER 42 > (defmacro gather-params (&rest body)
"Return plist of params"
`(list ,@(mapcar
(lambda (plist)
(if (typep (first plist) 'keyword)
(list 'list
''list
(first plist)
(second plist))
plist))
body)))
GATHER-PARAMS
CL-USER 43 > (let ((foo 1))
(gather-params (:mykey (+ foo foo)) (list 1 2 3)))
((LIST :MYKEY 2) (1 2 3))