A problem space can quickly be explored through code to test your assumptions. The design of code is easy to change as you are not managing type changes, Clojure is very good at managing data that would otherwise lead to exceptions.
As a dynamic language the code is quite terse, therefore it is easy to refactor.
Clojure has a REPL (Read Evaluate Print Loop), this is the Clojure run-time environment. You can define functions and data structures, then evalutate them to run either all your code or just a single expression. You can even change code and re-evaluate it whilst your application is still running and immediately see the effect that change has.
So the REPL is a very fast way to explore your problem domain with code
You could even connect to the REPL of a live system and change its behaviour without any down time (unless of course you write code that crashes).
Functions return a value (even if that value is nil) and you can therefore use a function as an argument to another function. This is termed as first order functions.
Clojure encourages a relatively pure approach to functional programming and Clojure can be considered immutable by default
One thing that keeps Clojure a small language is the fact that the same syntax is used to represent data and behaviour. For example, a function call is defined using a list, data structures and functions are defined using a list. In fact everything is a list, although we use a little syntatic sugar here and there to make the code quicker for a human to parse.
List, Map, Vector and Set are all built in data structures that are immutable.
If you run a function that seems to change a data structure, its actually returning a new data structure. Via a shared-memory model, new data structures are created cheaply as they share the common data elements from the original data structure and only include additional elements.
Lisp stands for LISt Processing, so its no surprise that all Clojure code is defined in a list.
The open Parenthesis (
denotes the start of a list, the first element of that list is evaluated as a function call, everthing else in the list is data.
The evaluation of the first element of a list can be behaviour of (
can be over-ridden using quote
or its short form '
so the list elements are all treated as data.
See Clojure arity and multi-methods for more information
Threads are much safe when you dont change state (eg. immutable state). Clojure is stateless by default.
Clojure helps you scale your applications by with a parrallel procssing approach, as you can run functions over immutable datastructures without conflict.
Clojure is compiled to bytecode that runs on the Java Virtual Machine. This helps Clojure run at a very high performance (close to Java, C++, etc.)
Clojure has a consise and easy to use Java Interoperability, enabling you to use any libraries that run on the JVM (Java, Groovy, Scala, Jruby, Jython, etc).
ClojureScript generated JavaScript that will run in a browser. ClojureCLR will compile to bytecode that runs on the Microsoft .Net platform.
Using atoms
or refs
in clojure you can have mutable data. Changes are done safely within Software Transactional Memory (STM), like having an in-memory ACID database managing access
Clojure uses macros
** Input & output with functional programming
Macros
Clojure emphasizes safety in its type system and approach to parallelism, making it easier to write correct multithreaded programs.
Clojure is very concise, requiring very little code to express complex operations.
Data centric design - a well constructed data structure helps define and clarify the purpose of the code
Modularity - Clojure and its community build things in modules / components that work together (in a similar design approach to the Unix file system, for example).
It offers a REPL and dynamic type system: ideal for beginners to experiment with, and well-suited for manipulating complex data structures.
A consistently designed standard library and full-featured set of core datatypes rounds out the Clojure toolbox.
Clojure is close to the speed of Java
Clojure relies on the JVM so there can be a longer boot time than a scripting language like Javascript. However, as you can connect to the Clojure runtime (the REPL) of a live system and because Clojure is dynamic, you can make changes to that live system without any downtime.
If you require more performance from Clojure, you can specify ahead of time compilation.