来自宏的函数调用的参数评估
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
函数的直接或间接使用)。
我有一个函数和一个调用该函数的宏。 为了看区别,我跟踪了这个函数,发现无论是直接调用还是从宏中调用都没有区别。 我想知道为什么从宏调用时没有评估参数。 我知道传递给宏的参数不会被评估,但即使从宏传递给函数的参数也会发生这种情况? 具体来说,我的意思是为什么 (< 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
函数的直接或间接使用)。