Stavros Macrakis <macrakis at alum.mit.edu> wrote:
Presumably the idea is to have the same *black-box* behavior. In the
current version of mopers/opers.lisp, it appears that the macro
definition has been *mechanically* converted to a regular function for
runtime use, which seems peculiar. For example, we have
(defun add (&rest terms)
(if (= (length terms) 2)
(apply #'add2 terms)
(apply #'addn `(,terms t))))
(define-compiler-macro add (&rest terms)
(if (= (length terms) 2)
`(add2 , at terms)
`(addn (list , at terms) t)))
Exactly. Your compiler macro removes some needless fucntion call and
linking overhead.
instead of what I'd have written by hand:
(defun add (&rest terms)
(if (= (length terms) 2)
(add2 (car terms) (cadr terms))
(addn terms t)))
> There is not requirement in the ANS that the implementation's compiler
> expand and use a compiler macro, although generally they do.
What is the ANS?
The language standard, rarely known as The American National Standard
for Programming Language Common Lisp (subsequently endorsed by ISO).
You can buy a poor scan pdf from ANSI, or there are convenient free html
versions available fron LispWorks (aka the Hyperspec) or franz. Both
html versions are believe faithful to the technical content of the ANS.
> You'll
> need to check each implementation to see if there are dependencies on
> the several optimize declaration qualities. ?(A compiler macro may _not_
> be expanded by the compiler is the function or macro is locally declared
> notinline.) ?You cannot otherwise ever depend on a compiled macro not
> being used, since implementations are permitted to accomplish
> `interpreted' execution, aka eval, as:
>
> ?(defun eval (form) (funcall (compile nil `(lambda () ,form))))
So presumably you should not write code like
(define-compiler-macro f (x) (f x)) ; punt to function
Cenceptually correct, but the correct version of youra definition would
be
(define-compiler-macro f (x) `(f ,x)) ; punt to function
There is a mechaniswm for a compiler macro to decline replacing the
call, thereby signifying that the original macro or function to be
treated normally. The compiler macro returns the whole original (eql)
form, in which case the compiler will treat the form in the normal
manner. This strange compiler macro gives a 20% discount if compiled on
a weekemd:
(defmacro maybe-discount (form) form)
(define-compiler-macro maybe-discount (&whole form x)
(if (> 4 (nth-value 6 (decode-universal-time (get-universal-time))))
`(* 0.8 ,x) ; 20% discount if compiled in a weekend
form) ;decline to discount on a weekday
)
but a more typical compiler macro would _look_ at its subforms, like
your add above, not when the form happens to get compiled.
because this could result in an infinite recursion (any more than you
could in the old macro system).
Right, but see the particular machinery above that allows a compiler
macro to decline to be expanded.
I wonder if there is a way to *force* the interpreted execution in
order to debug the macro?
Not portably, but usually there is if you know how your particular
implementation treats compiler macros. Remember, an implementation can
_always_ decline to use compiler macros. The language specification
requires a conforming definition accept and store a
define-compiler-macro form, but it isn't required to use the
definitions. Still, I believe all implementations do expand compiler
macros, with some varyance in details.