2015-12-07 84 views
1

我有一个函数和一个调用该函数的宏。 为了看到不同之处,我追踪了函数,发现它是直接调用还是从宏调用都没有区别。 我想知道为什么从宏调用参数时未被评估。 我知道传递给宏的参数不会被评估,但即使这发生在从宏传递给函数的参数上? 具体而言,我的意思是为什么(< 7 5)传递给GEN-口齿不清当没有评价为来自宏的函数调用的参数评估

功能:

(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) 

如果我只是做了这样的下面,它被评估为了。

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

回答

1

您的宏在宏扩展时调用函数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函数可能会要求额外的评估)。

+0

我假设一个函数的参数评估是递归的。奇怪的是,从我的角度来看,它只被评估一次。 – user1461328

1

gen-lisp返回它收到的任何参数。 作为函数,它不评估它的参数。 如果要进行评估的说法,你应该把它变成一个宏(你可能会想无论如何做,当你开始使用非平凡的方式binds参数)

4

您的宏:

(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)的结果。

记住:宏正在通过源代码。他们用代码进行计算。

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