9

I just started with macros and made a simple one to return maximum number out of a list.

(defmacro macro-max [list] (apply max list))

and If I make a function to do the same, it will be.

(defn  macro-max [list] (apply max list))

I am just exploring Clojure, so I don't know much.

I may sound completely silly to experts, But it looks like I can pretty much define a function instead of a macro.

4 Answers 4

9

The difference comes to life when you don't want to evaluate your arguments unless needed.

Consider this example:

(defn unless [pred body]
  (when (not pred)
    body))

This doesn't work since arguments to a function are eagerly evaluated. So body always runs, as shown below:

(unless (zero? 2)
        (prn "Not zero!"))
;; "Not zero!"

(unless (zero? 0)
        (prn "Not zero!"))
;; "Not zero!"

Both executions above print "Not zero!", which is clearly wrong.

The only way to write our unless utility is by using a macro:

(defmacro unless [pred body]
  `(when (not ~pred)
     ~@body))

Now if we give it a try, we'll see it works as expected:

(unless (zero? 2)
        (prn "Not zero!"))
;; "Not zero!"

(unless (zero? 0)
        (prn "Not zero!"))
;; this prints nothing

Macros only evaluate its arguments when the developer decides to.

You'll notice some special characters in the macro such as `, ~ and ~@. They stand for syntax-quote, unquote and unquote-splicing, respectively and are explained here.

I suggest you study these symbols.

Hope this helps.

Sign up to request clarification or add additional context in comments.

1 Comment

The syntax quote and unquote features are sometimes useful outside of macros as well.
1

If a function can do, then by all means use a function. Clojure libraries follow this rule, so probably most macros defined there cannot really be expressed as functions. Take the ->> macro:

(->> 
   "abcdefghij"
   (take 5)
   (drop 3)
   (apply str))

The above evaluates to "de". A function could not do that, since the arguments of the macro do not make sense when evaluated by themselves - (take 5) raises an error when evaluated.

What the macro does is modify the forms before they are evaluated (by inserting the previous expression as the last argument of the form.) This is what only a macro can do, not a function.

Comments

1

Macros are functions. The difference is only in evaluation time (macros are evaluated at macro expansion time, which is a step in compiling, functions are evaluated at runtime). Also, Macros work on S-Expressions (so macro is a bit like a function where you quote every single argument, i.e. you could easily replace any macro (mac a b) with a function (fun 'a 'b).

2 Comments

"you could easily replace any macro (mac a b) with a function (fun 'a 'b)". Definitely not easily. For this to work either a) the function would need to resolve the symbols in the context of the caller or b) the caller would have to eval the result of the function within own context. The b) would be closer to how macros work in reality.
@RafałDowgird I'm talking about what the macro does. The macro just works on S-expressions, and that's exactly what you can do with a 'normal' function too. That the result of a macro is inserted in place of the macro invocation is IMHO not that important when it comes to "Functions vs. Macros".
-7

I don't have experience with macros but it will allow you extend combilier by your functions. I am not sure but it is evaluated at runtime.

2 Comments

Why did you bother answeing if you don't have experience and are not sure?
Seriously. which part of your answer answers this question even by 1% ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.