I’m confused about the difference between a macro and a function; specifically why PART TWO fails below given that PART ONE succeeds.
(defun foo () "foo")
(setf a 3) ;; sets the symbol value cell to 3
(setf a #'foo) ;; PART ONE
(funcall a) ;; returns foo
(defmacro bar () "bar")
(setf b #'bar) ;; Error the macro name bar was found as an argument to function PART TWO
The
#(sharpsign) is a standard macro character which is a dispatch macro character. It’s supposed to compose with another character. The#'(sharpsign single-quote) combination expects a function name or lambda expression after it, and it expands to(function expression).So,
#'foois expanded at read-time to(function foo). Iffoois a function,functionwill evaluate to it. In a lexical scope, it may be afoofbound by afletorlabels. If there’s no such lexical definition, it’ll try to fetch the global function definition from the symbol’s function.Now,
(function bar)signals an error whenbarrepresents a macro, be it a lexicalmacroletor a globaldefmacro. You may, however, use(macro-function 'bar)to fetch the macro function of the globalbarmacro. If it exists, it’s a function of two arguments: a form and an environment.Unless you’re going to apply
bar‘s macro function to forms, it’s probably not what you want. Let’s think about applying the macro function ofand: it will not do a logical boolean operation, it’ll probably expand the given form into anif.However, if this is what you want, remember that
macro-functionhas a second optional parameter, an environment. You may get an environment as argument in adefmacroor in adefine-setf-expander. Within the latter, it’s usually needed so thatget-setf-expansiontakes into account the lexical environment in expanding a subform.Try this out:
Exercise: Implement your own
macroexpand-1andmacroexpand.Exercise: Implement a
macroexpand-all, amacroexpandthat recurses into subforms, recognizing Common Lisp’s special operators.Note: Don’t get too far with
macroexpand-all, it needs a code walker, which is implementation-specific.