Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Good examples of Clojure macros usage which demonstrate advantages of the language over the mainstream?

Tags:

macros

clojure

I am thinking about learning Clojure, but coming from the c-syntax based (java, php, c#) world of imperative languages that's going to be a challenge, so one naturally asks oneself, is it really worth it? And while such question statement can be very subjective and hard to manage, there is one specific trait of Clojure (and more generally, the lisps) that I keep reading about, that is supposed to make it the most flexipowerful language ever: the macros.

Do you have any good examples of macro usage in Clojure, for purposes which in other mainstream languages (consider any of C++, PHP, Perl, Python, Groovy/Java, C#, JavaScript) would require much less elegant solutions/a lot of unnecessary abstraction/hacks/etc.

like image 819
Cray Avatar asked May 03 '12 15:05

Cray


People also ask

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.

Why use Clojure?

Clojure is a good choice for a wide variety of projects. You can use it from social networking industry to Big Data solutions. Initially, Clojure language was targeted for working with JVM. So, the most popular modern Clojure implementation uses the Java Virtual Machine.


1 Answers

I find macros pretty useful for defining new language features. In most languages you would need to wait for a new release of the language to get new syntax - in Lisp you can just extend the core language with macros and add the features yourself.

For example, Clojure doesn't have a imperative C-style for(i=0 ;i<10; i++) loop but you can easily add one with a macro:

(defmacro for-loop [[sym init check change :as params] & steps]   (cond     (not (vector? params))        (throw (Error. "Binding form must be a vector for for-loop"))     (not= 4 (count params))        (throw (Error. "Binding form must have exactly 4 arguments in for-loop"))     :default       `(loop [~sym ~init value# nil]          (if ~check            (let [new-value# (do ~@steps)]              (recur ~change new-value#))            value#)))) 

Usage as follows:

(for-loop [i 0, (< i 10), (inc i)]   (println i)) 

Whether it is a good idea to add an imperative loop to a functional language is a debate we should probably avoid here :-)

like image 169
mikera Avatar answered Oct 26 '22 11:10

mikera