I have a function and one macro in which the function is called. And to see the difference, I trace the function and found that there was no difference whether it is called directly or from the macro. I wonder why the parameter was not evaluated when called from macro. I know that parameters passed to a macro will not be evaluated but even this happens to the parameters passed to a function from a macro? To be specific, I mean why (< 7 5) is not evaluated to nil when passed to gen-lisp
The function:
(defun gen-lisp (expr binds)
expr)
The macro:
(defmacro dsptch-prove-query (query binds)
`(if (eq (car ',query) 'lisp)
,(gen-lisp (cadr query) binds)
(prove-query ',query ,binds)))
Result when called from macro:
(dsptch-prove-query (lisp (< 7 5)) nil)
1. Trace: (GEN-LISP '(< 7 5) 'NIL)
1. Trace: GEN-LISP ==> (< 7 5)
NIL
Result when called directly:
(gen-lisp '(< 7 5) 'NIL)
1. Trace: (GEN-LISP '(< 7 5) 'NIL)
1. Trace: GEN-LISP ==> (< 7 5)
(< 7 5)
And if I just do it like this below, it is evaluated to nil already.
(gen-lisp (< 7 5) nil)
1. Trace: (GEN-LISP 'NIL 'NIL)
1. Trace: GEN-LISP ==> NIL
NIL
Your macro calls the function gen-lisp
at macro-expansion time in order to compute a part of the macro-expansion.
The expression which calls the function is this:
(gen-lisp (cadr query) binds)
this is a function call, which specifies two argument expressions: (cadr query)
and binds
. These expressions most certainly are evaluated as forms and their resulting values constitute the arguments which the function receives.
The macro's query
parameter's argument value is the nested list object (lisp (< 7 5))
and so (cadr query)
calculates the object (< 7 5)
. Of course this itself isn't evaluated as a form. Evaluation is done, and (< 7 5)
is its result, which gets passed into the function as its leftmost argument.
What's going on inside the macro is very similar to this:
(let ((query '(lisp (< 7 5))) ;; analogous to macro's query param
(binds nil))
(gen-lisp (cadr query) binds)) ;; of course (< 7 5) not evaled
If (< 7 5)
were reduced to nil
, that would be a double evaluation. Nothing in the code calls for a double evaluation. (For instance, we do not see any direct or indirect use of the eval
function which could request that extra evaluation).