Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between defn and defmacro?

Tags:

clojure

What is the difference between defn and defmacro? What is the difference between a function and a macro?

like image 444
Belun Avatar asked Sep 08 '10 11:09

Belun


People also ask

What is meant by macro function?

In general, a macro language function processes one or more arguments and produces a result. You can use all macro functions in both macro definitions and open code. Macro functions include character functions, evaluation functions, and quoting functions.


2 Answers

defn defines a function, defmacro defines a macro.

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.

like image 83
sepp2k Avatar answered Sep 28 '22 05:09

sepp2k


The Other answers cover this well in depth so I'll try to cover it as succinctly as I can. I would appreciate edits/comments on how to write it more succinctly while keeping it clear:

  • a function transforms values into other values.
    (reduce + (map inc [1 2 3])) => 9

  • a macro transforms code into other code.
    (-> x a b c) => (c (b (a x))))

like image 27
Arthur Ulfeldt Avatar answered Sep 28 '22 06:09

Arthur Ulfeldt