(def pointless (fn [n] n))
"Whatever is passed to this macro---a list, a symbol, whatever---will be returned unmolested and then evaluated after the call. Effectively, calling this macro is pointless:"
(pointless (+ 3 5)) ; pointless returns the list (+ 3 5), which is then evaluated in its place (+ 3 5) ; may as well just write this instead
No. Macro arguments are passed as unevaluated forms. However, numbers
and data structures are still usable. If you pass 3 to a macro you can
add to it, check that it's odd, etc. in the macro; if you pass [7 8 (*
4 5)] the macro code sees, and can traverse, a vector with the
integers 7 and 8 in it -- but the last component of the vector will be
the list '(* 4 5) rather than the number 20.
The macro can always emit code that will process the evaluated items.
For example, it can emit `(reduce + ~v) with v having been that
vector, and the output of '(reduce + [7 8 (* 4 5)]) will evaluate to
35, as it should.
If you understand the reader and evaluator, there actually isn't all that much more to understand about the operation and creation of macros, for a macro is simply a regular function that is called in a special way. When called as a macro, a function takes its arguments unevaluated and returns an expression to be evaluated in place of the call to the macro. A very simple (and pointless) macro would be one that simply returns its argument. *Here's a first attempt which is NOT a macro:*
(def pointless (fn [n] n))
Whatever is passed to this macro---a list, a symbol, whatever---will be returned unmolested and then evaluated after the call. *At least, that's what we want to happen, and that's what would happen to a real macro. But this is not a real macro yet.* Effectively, calling this macro is pointless: *And if this were a real macro, this is what would happen:*
(pointless (+ 3 5)) ; pointless returns the list (+ 3 5), which is then evaluated in its place (+ 3 5) ; may as well just write this instead
But as we defined pointless above, it is just a regular function, not a macro. *The argument to pointless (+ 3 5) gets evaluated to 5 and then enters the body of the function, which simply returns 5.* To make it a macro, we need to attach the key-value pair :macro true
as metadata to the Var mapped to pointless by the def
. There are a number of ways to do this, but most commonly we would simply define the function as a macro with the provided macro clojure/defmacro:
(defmacro pointless [n] n) ; define a macro pointless that takes one parameter and simply returns it *...without evaluating it -- now it behaves as we intended in the previous code snippet on this page*