5 Answers
5

The difference between functions and macros is that on a function call first the arguments of the function are evaluated then the body of the function is evaluated using the arguments.

Macros on the other hand describe a transformation from one piece of code to another. Any evaluation takes place after the transformation.

This means that arguments may be evaluated multiple times or not at all. As an example or is a macro. If the first argument of or is false, the second argument will never be evaluated. If or were a function, this would not be possible, because the arguments would always be evaluated before the function runs.

Another consequence of this is that the arguments of a macro need not be a valid expression before the macro is expanded. For example you could define a macro mymacro such that (mymacro (12 23 +)) expands to (+ 23 12), so this will work even though (12 23 +) on its own would be nonsense. You couldn't do that with a function because (12 23 +) would be evaluated, and cause an error, before the function runs.

A small example to illustrate the difference:

(defmacro twice [e] `(do ~e ~e))
(twice (println "foo"))

The macro twice gets the list (println "foo") as an argument. It then transforms it into the list (do (println "foo") (println "foo")). This new code is what gets executed.

(defn twice [e] `(do ~e ~e))
(twice (println "foo"))

Here println "foo" is evaluted right away. Since println returns nil, twice is called with nil as its argument. twice now produces the list (do nil nil) and returns that as its result. Note that here (do nil nil) is not evaluated as code, it's just treated as a list.

what do you mean by "arguments may be evaluated multiple times" when referring to macros ? can you give an example or explain more ?
–
BelunSep 8 '10 at 12:25

1

I don't think anybody would do this, but imagine a forloop macro. You might invoke it as (forloop [x 0] (< x 10) (+ x 1) (print x)). The clauses (< x 10), (+ x 1), and (print x) would not get evaluated up front, but would get evaluated for every iteration of the loop. For that reason, this could only be implemented as a macro. A function would evaluate its arguments greedily. Macros are one way to achieve laziness in Clojure.
–
Daniel YankowskySep 8 '10 at 12:38

I think this explanation miss an important point. The first difference between macro and function is the time of their evaluation. A macro is evaluated at compile-time, a function is called at runtime. All the other differences come from that difference.
–
Nicolas OurySep 13 '10 at 17:14

2

@Nicolas: I don't agree (about everything else following from that, I mean). Non-recursive functions called with constant arguments, are also often evaluated at compile-time as an optimization, but they still don't have any of the properties that macros have. Also it's perfectly possible to write an implementation of clojure that is entirely interpreted (and thus would have no compile-time) and which would still behave exactly like the official clojure implementation. I.e. macro expansion happening at compile-time is an implementation detail.
–
sepp2kSep 13 '10 at 18:30

A macro is like having an apprentice programmer that you can write notes to:

Sometimes, if I'm trying to debug something, I like to change something like

(* 3 2)

Into something like this:

(let [a (* 3 2)] (println "dbg: (* 3 2) = " a) a)

Which works the same way, except that it prints out the expression it
has just evaluated, and its value, as well as returning the value as the result of the
whole expression. This means that I can leave my code undisturbed whilst examining intermediate values.

This can be very useful, but it's time consuming and error prone to type. You might imagine
delegating such tasks to your apprentice!

Rather than hiring an apprentice, you can program the compiler to do these things for you.

Try to write a function dbgf that does the same thing, and you'll have problems, because (dbgf (* 3 2)) -> (dbgf 6) before dbgf is called, and so whatever dbgf does, it can't recover the expression that it needs to print out.

I'm sure you can think of many ways round this, like run-time evaluation or passing in a string. Try to write dbg using defn instead of defmacro. It will be a good way to convince yourself that macros are good things to have in a language. Once you've got it working,
try using it on an expression that has a side effect as well as a value, like

(dbg (print "hi"))

In fact macros are so good to have that we're prepared to live with the (brackety ((syntax))) of LISPs in order to get them. (Although I must say that I rather like it for its own sake (but then (I am) a bit weird (in the head)).

C also has macros, which work in roughly the same way, but they're always going wrong, and to get them right you need to put so many brackets into your program that it looks like LISP!

You're actually recommended not to use C's macros because they're so error prone, although I have seen them used to great effect by people who really knew what they were doing.

LISP macros are so effective that the language itself is built out of them, as you'll notice if you look at the Clojure source files that are themselves written in Clojure.

The base language is very simple so that it's easy to implement, and then the complex superstructure is built up using macros.

I do hope this helps. It's rather longer than my usual answers, because you've asked a deep question. Good luck.

C macros are not like Lisp macros. C macros operate on the text, i.e. on the string of characters making up your source code, while Lisp macros operate on the abstract syntax tree, i.e. the program structure.
–
SvanteSep 8 '10 at 16:35

your example code is a bit to much for a newbie. try explaining the extra stuff in your examples : x#, ~x, '~x. try explaining your way of thinking that got you to the solution, this way a newbie like me can get you :)
–
BelunSep 9 '10 at 0:31

I will try to. It will take me a while. I'll post a link here when it's done.
–
John Lawrence AspdenSep 9 '10 at 11:16

Without sounding snarky, one creates a function, while the other creates a macro. In Common Lisp (and I'll assume this applies to clojure as well), Macros are expanded before actual compilation of functions. So, lazy-cat:

defn define a function, and defmacro define a macro.
Macro is like a function but treat it's argument (if they are expressions as data), then process them and return data (list of symbols which are the code) and then evaluate that return code. So it's replace one code with another (on compile time).