What @Constantine said about lexical and dynamic scoping is true, and it explains the difference from Common Lisp behavior.
However, there is something misleading in your question. This really has nothing to do with macroshas nothing to do with macros. Here is a definition using defun
instead of defmacro
. Note that you need a quote mark ('
) before the use of ,function
: ',function
, because you want 'zerop
and not zerop
(which would be evaluated as a variable).
(defun complement (function)
"Return a function that complements the effect of FUNCTION.
The resulting function applies FUNCTION to any number of args
and returns the Boolean complement of the result."
`(lambda (&rest args)
(not (apply ',function args))))
(funcall (complement #'zerop) 0) ; Returns nil
(funcall (complement #'zerop) 3) ; Returns t
(complement #'zerop) ; Returns (lambda (&rest args) (not (apply (quote zerop) args)))
When you use complement
that list is evaluated to a function and used as such.
So the difference between this approach and the use of free variable function
in the lexical binding case (that is, the use of a closure that accompanies the lambda form that has free variable function
with an environment in which that variable is bound to zerop
) is that:
In this approach there is no variable in the resulting form, and
The resulting form is a list, not a function.
Number 1 means that you cannot use the variable for anything when the lambda form is used as a function, because, hey! - it isn't there.
And it means that unless you explicitly go to the trouble of byte-compiling the resulting form (which is a list, whose car is lambda
etc.), evaluation is slower, because you are interpreting a list as a lambda form and that as a function - you do not have a (possibly byte-compiled) function directly.
When might you care whether you have a variable at the time the function is used? When you need to do something with that variable as a variable! For example, you assign it another value than function
at some point. In most cases you do not need the variable as a variable - it is enough to have its value (in this case, zerop
) when the function is used.