question from wikibooks page on macros?

18 views
Skip to first unread message

Andrew

unread,
Jan 6, 2012, 11:12:56 AM1/6/12
to clo...@googlegroups.com
http://en.wikibooks.org/wiki/Learning_Clojure/Macros

The page says the following:

(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

But actually, doesn't (+ 3 5) get evaluated before pointless ever sees it? Or am I mistaken?

Cedric Greevey

unread,
Jan 6, 2012, 11:28:32 AM1/6/12
to clo...@googlegroups.com

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.

Jeff Heon

unread,
Jan 6, 2012, 11:29:23 AM1/6/12
to Clojure
You are right. Keep reading a bit and it says "But as we defined
pointless above, it is just a regular function, not a macro."
And you can verify the pointless macro using macro-expand as shown
later.(macroexpand '(pointless (+ 3 5)))=>  (+ 3 5)
On Jan 6, 11:12 am, Andrew <ache...@gmail.com> wrote:
> http://en.wikibooks.org/wiki/Learning_Clojure/Macros
>
> The page says the following:
>
> (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
>
> But actually, doesn't (+ 3 5) get evaluated *before *pointless ever sees it?
> Or am I mistaken?

Andrew

unread,
Jan 6, 2012, 11:49:39 AM1/6/12
to clo...@googlegroups.com
I see. That section is just horribly written, calling something a macro when it isn't one yet. Here's my thinking in *bold*, inlined.

Simple Macro

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*
Reply all
Reply to author
Forward
0 new messages