从 plist 宏体中提取并执行 closure/lambda
Extracting and executing a closure/lambda from a plist macro body
我正在尝试创建一个应该像这样使用的宏 (bar
):
(let ((my-var "foo"))
(bar ("some")
:buzz (lambda () (format t "~a~%" my-var))))
宏应该基本上只是 FUNCALL lambda 并考虑 MY-VAR。
我想出的是:
(defmacro bar ((thing) &body body)
`(funcall (coerce (getf (list ,@body) :buzz) 'function)))
这有效,它打印“foo”。
但我想知道这是不是这样做的,或者是否有更好的方法。
嗯,首先,如果您不需要额外的、未使用的参数,那么这只是 funcall
,因为 (lambda ...)
表示一个函数。
(let ((my-var "foo"))
(funcall (lambda () (format t "~a~%" my-var))))
因此,即使您不想调用此 funcall
,您也可以将其编写为函数,而不是宏:它不进行任何代码转换。但大概你确实需要这个额外的参数,并且你打算在扩展中将它用于某种目的,所以你需要的是一个宏,它接受关键字参数并扩展成合适的 funcall
形式:
(defmacro bar ((thing) &key (buzz '(lambda ())))
(declare (ignore thing))
`(funcall ,buzz))
我正在尝试创建一个应该像这样使用的宏 (bar
):
(let ((my-var "foo"))
(bar ("some")
:buzz (lambda () (format t "~a~%" my-var))))
宏应该基本上只是 FUNCALL lambda 并考虑 MY-VAR。
我想出的是:
(defmacro bar ((thing) &body body)
`(funcall (coerce (getf (list ,@body) :buzz) 'function)))
这有效,它打印“foo”。 但我想知道这是不是这样做的,或者是否有更好的方法。
嗯,首先,如果您不需要额外的、未使用的参数,那么这只是 funcall
,因为 (lambda ...)
表示一个函数。
(let ((my-var "foo"))
(funcall (lambda () (format t "~a~%" my-var))))
因此,即使您不想调用此 funcall
,您也可以将其编写为函数,而不是宏:它不进行任何代码转换。但大概你确实需要这个额外的参数,并且你打算在扩展中将它用于某种目的,所以你需要的是一个宏,它接受关键字参数并扩展成合适的 funcall
形式:
(defmacro bar ((thing) &key (buzz '(lambda ())))
(declare (ignore thing))
`(funcall ,buzz))