是否有一种方法可以使宏进行额外的评估,然后再返回结果



我试图让我的宏对结果进行额外评估,然后再返回结果。如果没有eval

可以做到这一点

我正在尝试在下面的练习4中解决问题:

  1. 定义一个宏观nth-Expr,该宏nth-expr采用整数n和任意数量的表达式,评估nth表达式并返回其值。如果您认为第一个论点是字面整数。
  2. ,此练习很容易解决。

4。作为练习3,但假设第一个参数是要评估的表达式。

很容易获得宏来选择正确的表达:

(defmacro nth-expr% (n &rest es)
  `(nth ,n ',es))
CL-USER> (defvar i 1)
I
CL-USER> (nth-expr% (1+ i) (+ 2 3) (- 4 3) (+ 3 1))
(+ 3 1)

表达式(+ 3 1)是我们想要的,但是我们希望宏将其评估为4。

当然可以通过评估来完成:

(defmacro nth-expr%% (n &rest es)
  `(eval (nth ,n ',es)))
CL-USER> (nth-expr%% (1+ i) (+ 2 3) (- 4 3) (+ 3 1))
4

但是还有另一种方法吗?

感觉解决方案应该是将nth-expr%的主体放在辅助宏中,并且顶级宏仅包含对此助手的无引用的呼叫:

(defmacro helper (n es)
  `(nth ,n ',es))
(defmacro nth-expr (n &rest es) ; doesn't work!
  (helper n es))

的想法是,呼叫helper将返回(+ 3 1),这将是调用nth-expr的呼叫的扩展,在运行时会评估4.当然会爆炸,因为NES获取被视为文字。

这并不容易。

使用eval不好,因为eval不评估本地词汇环境中的代码。

请记住,如果我们允许评估表达式以确定要执行的另一个表达式的数量,那么我们在宏扩展时间不知道此数字 - 因为该表达式可以基于需要计算的值 - 例如基于某些变量:

(nth-expression
   foo
 (bar)
 (baz))

所以我们可能想考虑执行此操作的代码:

(case foo
  (0 (bar))
  (1 (baz)))

CASE正在评估foo,然后使用结果来找到其头部具有相同值的子句。然后将评估该条款的结果形式。

现在我们需要编写将前者扩展到后者的代码。

这将是一个非常简单的版本:

(defmacro nth-expression (n-form &body expressions)
  `(case ,n-form
     ,@(loop for e in expressions
             and i from 0
             collect `(,i ,e))))

问题:使用CASE的缺点可能是什么?

knuto:Rainer Joswig可能会要求您考虑案件陈述的工作原理。也就是说,在评估密钥形式(即,第一个参数(之后,将将其顺序比较与每个子句中的密钥进行比较,直到找到匹配为止。如果有很多条款,则可能会耗时。您可以通过仔细在HypersPec中读取case的条目(因为他不止一次地坚持我愿意(:

评估密钥形式或密钥位置以产生测试键。每一个 然后依次考虑正常示例。

还要注意,构建许多case条款将增加在编译时扩展和编译宏的时间。

关于您在nth-expr%%中使用eval,您仍然可以通过切换到apply来实现评估的效果:

(defmacro nth-expr%% (n &rest es)
  `(let ((ne (nth ,n ',es)))
     (apply (car ne) (cdr ne))))

但请参阅http://www.gigamonkeys.com/book/macros-defining-your-own.html上的泄漏。

通常,处理表达式的一种更有效的方法是简单的向量,而不是列表。(问题语句不排除向量表示。(虽然nthcase涉及一单个表达式搜索,但诸如arefsvref之类的函数可以直接索引中。假设表达式向量与索引一起传递给宏,也许首先需要 (coerce expressions 'simple-vector),如果列表,则可以在恒定时间内计算结果,无论有多少个表达式:

(defmacro nth-expr%%% (n es)
  `(let ((ne (svref ',es ,n)))
     (apply (car ne) (cdr ne))))

现在

(defvar i 1)
(nth-expr%%% (1+ i) #((+ 2 3) (- 4 3) (+ 3 1))) -> 4

相关内容

  • 没有找到相关文章

最新更新