Why Clojure?

Less code means less bugs. With less code it is easier to get close to 90%+ code coverage as there is less code to test. It is also easier to maintain as there is less code to look through for bugs or refactoring. In many cases Clojure is an order of magnitude smaller than traditional OO languages like C++ or Java.

Java Example:

public class Fibonacci {
    public static long fib(int n) {
        if (n <= 1) return n;
        else return fib(n-1) + fib(n-2);
    }


    public static void main(String[] args) {
        int N = Integer.parseInt(args[0]);
        for (int i = 1; i <= N; i++)
            System.out.println(i + ": " + fib(i));
    }
}

Clojure Example:

(let [n 10]
  (def fib-seq
    (take n (lazy-cat [0 1] (map + (rest fib-seq) fib-seq))))

 

 

 

Much less scaffolding code.


The feature I use the most that allows for quick testing of a function is the read–eval–print loop (REPL). This allows testing of functions without having to build the whole application. Function programming involves writing functions that take a specific input and return a known output, it does not rely on all the scaffolding that Java, C++, C# require like classes. All this scaffolding takes time to develop before you can even begin to test functionality. This can be an accelerator for teams using TDD.

Languages like Java require that everything is a Class, Clojure instead deals with data. This also makes testing easier as the tests don't need to create instances of classes, instead just pass the data along.


Java Example:

Vector<Customer> customers = new Vector<Customer>();
// helper function to populate the customers vector.
populateCustomerData(customers);
Vector<String> customerLastNames = CustomerUtils.getLastNames(customers);

assertEquals(customerLastNames.size(), 2);
assertEquals(customerLastNames.get(0), "Doe");
assertEquals(customerLastNames.get(1), "Smith");


Clojure Example:

(let [customers [{:first "John" :last "Doe"} {:first "Joe" :last "Smith"}]
      last-names (get-customer-last-names customers)]
(is (= (count last-names) 2))
(is (= "Doe" (nth last-names 0))
(is (= "Smith" (nth last-names 1)))))

 

Discourages mutable state

While Clojure does provide a means to mutate state, the mechanisms to do so insure consistency across threads. Mutable state is discouraged as changing states within a function results in side-effects which are less predictable than dealing with immutable state. Side-effects lead to more subtle bugs that are harder to locate. Since Clojure discourages mutating state bugs are typically easier to identify than in other imperative languages.

Parallelism

Processors clock speed is not getting faster, instead more cores are being added. If your application is not written to take advantage multiple cores your application will be limited to the clock speed of the processor.

More traditional Object Oriented languages like Java and C++ are adding more mechanisms to support Parallelism, but it requires using third party libraries and using boiler plate macros, templates or classes. Clojure supports parallelism out of the box. Since state is immutable this means that developers do not need to worry about maintaining consistent state across multiple thread/processors. Something that imperative languages do not have the luxury of doing.

Unit Testing

Clojure being a functional language means that functions are taking an input and returning an output. They are not mutating some member variable of say a class. Nor do these functions belong to classes. So this reduces a any boiler plate code needed to setup classes within unit tests.

Because they don't belong to classes the concept of hidden arguments (Calling a function on a member variable to get data) it makes it much more explicit what is being tested, and less likely to introduce side-effects.

Leverage Java and JVM (or CLR)

Clojure runs on the JVM, and can call Java directly. Or Java can call Clojure. This allows developers to leverage the best of both languages, and the large community support in both languages. Some aspects or a program maybe better handled with Object Oriented Design so use Java. While other areas may lend itself better to functional programming. There is also a ClojureCLR version that runs on the Common Language Runtime (CLR) that would allow developers more familiar with C# and .Net to leverage that instead of Java and the JVM.