gpt4 book ai didi

macros - 评估宏形式的参数

转载 作者:行者123 更新时间:2023-12-04 19:10:10 26 4
gpt4 key购买 nike

有选择地将评估参数传递给宏形式的最佳实践是什么?

详细说明:宏的用处在于它能够接收未评估的参数,这与函数形式的默认评估规则不同。但是,评估宏参数有一个合法的用例。

考虑一个人为的例子:

(defparameter *func-body* '((print i) (+ i 1)))

假设 *func-body*可以作为宏的主体 our-defun定义为:
(defmacro our-defun (fun args &body body)
`(defun ,fun ,args ,@body))

所以在 (our-defun foo (i) (+ 1 i)) 之后, 我们可以说 (foo 1)获取 2 .但是,如果我们使用 (our-defun foo (i) *func-body*)(foo 1) 的结果将是 ((PRINT I) (+ I 1)) (即 *func-body* 的值)。如果我们可以强制对 *func-body* 进行评估,那就太好了。作为宏的参数 our-defun .

目前,我可以想到一种使用 compile 的技术和 funcall要做到这一点,如
(funcall (compile nil `(lambda () (our-defun foo (i) ,@*func-body*))))

之后 (our-defun 1)将打印出 1 并返回 2 , 如预期。我可以想到使用 eval 进行这项工作的案例,但我宁愿远离 eval由于其在范围界定方面的特殊性。

这导致我一开始的问题,有没有更直接或本地的方式来做到这一点?

PS,

函数 (UPDATE-HOOK) 中有一个不太人为的例子。 ,它使用两个库宏 (ADD-HOOK)(REMOVE-HOOK)并且需要评估它的参数。 (funcall (compile nil `(lambda () ...)))上面的技术在这里使用。
(defun update-hook (hook hook-name &optional code)
(funcall (compile nil `(lambda () (remove-hook ,hook ',hook-name))))
(unless (null code)
(compile hook-name `(lambda () ,@code))
(funcall (compile nil `(lambda () (add-hook ,hook ',hook-name))))))

最佳答案

这有点困惑。宏不接收未评估的参数。

宏获取源代码并从中创建源代码。还要记住,Lisp 中的源代码实际上是作为数据提供的。宏创建代码,它评估一些形式而一些不评估。

宏需要在编译系统中工作。运行前。在编译期间。宏看到的只是源代码,然后它从中创建源代码。将宏视为代码转换,而不是评估参数。

It would be nice if we can force the evaluation of *func-body* as an argument to the macro our-defun



那不是很干净。在已编译的系统中,您需要确保 *func-body*实际上有一个有用的绑定(bind),它可以在 解决。编译时间 .

如果你有一个像 DEFUN 这样的宏,让源代码静态化是有意义的。如果你想在表单中插入一些源代码,那么在读取时这样做是有意义的:
(defun foo (i) #.`(,@*foo*))

但这是我通常想要避免的代码。

two library macros (ADD-HOOK) and (REMOVE-HOOK) and needs to evaluate its parameters.



为什么要 ADD-HOOKREMOVE-HOOK是宏?如果你没有真正的理由,它们就应该是函数。已经因为它们使重用变得困难。

如果你想做 ADD-HOOKREMOVE-HOOK出于某种原因宏,然后 UPDATE-HOOK通常也应该是一个宏。

关于macros - 评估宏形式的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15669675/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com