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 macros. Here is a definition using
defun instead of
defmacro. Note that you need a quote mark (
') before the use of
',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
',function you are not leaving
function as a free variable in the resulting function (lambda form). Instead, because of the backquote surrounding the comma, the value of FUNCTION that is passed to function
complement is substituted for
,function, and then quoted.
zerop is passed as argument to
complement it is substituted for
,function and then quoted, producing
'zerop within the resulting lambda form. The backquote expression constructs a list:
(lambda (&rest args) (not (apply '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 couples (a) the lambda form that has free variable
function with (b) 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.