2015-12-07 85 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)的結果。

記住:宏正在通過源代碼。他們用代碼進行計算。

只是傳遞代碼不會評估代碼。