来自宏的函数调用的参数评估

parameter evaluation of function call from a macro

我有一个函数和一个调用该函数的宏。 为了看区别,我跟踪了这​​个函数,发现无论是直接调用还是从宏中调用都没有区别。 我想知道为什么从宏调用时没有评估参数。 我知道传递给宏的参数不会被评估,但即使从宏传递给函数的参数也会发生这种情况? 具体来说,我的意思是为什么 (< 7 5) 在传递给 gen-lisp[= 时未被评估为 nil 31=]

函数:

(defun gen-lisp (expr binds)
  expr)

宏:

(defmacro dsptch-prove-query (query binds)
  `(if (eq (car ',query) 'lisp)
       ,(gen-lisp (cadr query) binds)
     (prove-query ',query ,binds)))

从宏调用时的结果:

 (dsptch-prove-query (lisp (< 7 5)) nil)
1. Trace: (GEN-LISP '(< 7 5) 'NIL)
1. Trace: GEN-LISP ==> (< 7 5)
NIL

直接调用结果:

 (gen-lisp '(< 7 5) 'NIL)
1. Trace: (GEN-LISP '(< 7 5) 'NIL)
1. Trace: GEN-LISP ==> (< 7 5)
(< 7 5)

如果我像下面这样做,它已经被评估为 nil

(gen-lisp (< 7 5) nil)
1. Trace: (GEN-LISP 'NIL 'NIL)
1. Trace: GEN-LISP ==> NIL
NIL

gen-lisp returns 它收到的任何参数。 作为一个函数,它不会计算它的参数。 如果你想评估参数,你应该把它变成一个宏(当你开始以非平凡的方式使用 binds 参数时你可能想要这样做)

您的宏是:

(defmacro dsptch-prove-query (query binds)
  `(if (eq (car ',query) 'lisp)
       ,(gen-lisp (cadr query) binds)
     (prove-query ',query ,binds)))

宏调用函数gen-lisp。参数由 (cadr query)binds 计算得出。 query 是一个列表。 (cadr query) 计算该列表的第二个元素。这就是正在进行的评估。没有理由它应该评估 (cadr query).

的结果

记住:宏正在获取源代码。他们用代码计算。

只是传递代码并不会评估代码。

您的宏在宏展开时调用函数 gen-lisp 以计算一部分宏展开。

调用函数的表达式是这样的:

(gen-lisp (cadr query) binds)

这是一个函数调用,它指定了两个参数表达式:(cadr query)binds。这些表达式 肯定是 作为形式计算的,它们的结果值构成函数接收的参数。

宏的 query 参数的参数值是嵌套列表对象 (lisp (< 7 5)),因此 (cadr query) 计算对象 (< 7 5)。当然这个 本身 不被评估为一种形式。评估完成,(< 7 5) 是其结果,作为最左边的参数传递给函数。

宏内部发生的事情与此非常相似:

(let ((query '(lisp (< 7 5)))  ;; analogous to macro's query param
      (binds nil))
  (gen-lisp (cadr query) binds)) ;; of course (< 7 5) not evaled

如果(< 7 5)减少到nil,那就是双重评估。代码中没有任何内容需要双重评估。 (例如,我们没有看到任何可以请求额外评估的 eval 函数的直接或间接使用)。