Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Clojure how is a macro different from a function?

Tags:

clojure

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.

like image 999
Amogh Talpallikar Avatar asked Apr 15 '13 06:04

Amogh Talpallikar


People also ask

How is a macro different from a function?

A macro is defined with the pre-processor directive. Macros are pre-processed which means that all the macros would be processed before your program compiles. However, functions are not preprocessed but compiled.

What are macros in Clojure?

Clojure has a programmatic macro system which allows the compiler to be extended by user code. Macros can be used to define syntactic constructs which would require primitives or built-in support in other languages. Many core constructs of Clojure are not, in fact, primitives, but are normal macros.

What is a Clojure function?

Clojure is a functional language. Functions are first-class and can be passed-to or returned-from other functions. Most Clojure code consists primarily of pure functions (no side effects), so invoking with the same inputs yields the same output.


1 Answers

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.

like image 181
leonardoborges Avatar answered Oct 04 '22 03:10

leonardoborges