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
Macros are not functions. Thus you can't get a function object from a macro name. You can apply functions, but not macros.
A macro expects source code and generates new source code.
Common Lisp is defined in such a way that this can be done at compile time, before runtime. Common Lisp does not support runtime macro expansions in the general case. Common Lisp does that so that code can be compiled completely before running. One of the goals when defining Common Lisp was to define it as a language which allows efficient execution of large Lisp programs. Runtime code generation is only useful in a controlled manner - otherwise a whole new class of execution errors might happen at runtime. A macro mechanism which would allow general runtime code manipulation was not seen as desirable.
In older Lisp dialects there was the idea of so called FEXPRs, which are something like macros which can be called at runtime and which can manipulate source as runtime. This feature was removed for Common Lisp. For background on this see Special Forms in Lisp by Kent Pitman.
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, #'foo is expanded at read-time to (function foo). If foo is a function, function will evaluate to it. In a lexical scope, it may be a foo fbound by a flet or labels. 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 when bar represents a macro, be it a lexical macrolet or a global defmacro. You may, however, use (macro-function 'bar) to fetch the macro function of the global bar macro. 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 of and: it will not do a logical boolean operation, it'll probably expand the given form into an if.
However, if this is what you want, remember that macro-function has a second optional parameter, an environment. You may get an environment as argument in a defmacro or in a define-setf-expander. Within the latter, it's usually needed so that get-setf-expansion takes into account the lexical environment in expanding a subform.
Try this out:
(funcall (macro-function 'and) '(and form1 form2 form3) nil)
Exercise: Implement your own macroexpand-1 and macroexpand.
Exercise: Implement a macroexpand-all, a macroexpand that 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With