Clojure leads to a very component based approach to development. There are no huge and bloated frameworks in Clojure. The core is very small. Hundreds of focused libraries to use in collaboration.
Boiled down to the most simplest structure, Clojure applications you write typically look like this:
;; define a namespace
(ns name-space.name)
;; define one or more immutable data structures - the fewer the better typically
(def my-data-struture [[{}{}]])
;; define behaviour that acts on data structures inside one or more functions
(defn my-function [paramter]
(my-behaviour parameter))
;; Call those functions to make your application do something
(my-behaviour data)
As functions always evaluate to a value, a function can be used as an argument to another function (or itself if you get recursive !!)
Clojure has 4 built in persistent data structures (list, map, vector, set), however the most commonly used for specificaly manipulating data are map
and vector
or some combination of the two.
A vector is similar to an array in that its an indexed collection optomised for random access.
A map is a key value pair, with the keys typically represented with clojure keywords
Some examples of using these data structures this are:
;; A map of maps of maps with occasional vectors
{:starwars {
:characters {
:jedi ["Luke Skywalker"
"Obiwan Kenobi"]
:sith ["Darth Vader"
"Darth Sideous"]
:droids ["C3P0"
"R2D2"]}
:ships {
:rebel-alliance ["Millenium Falcon"
"X-wing figher"]
:imperial-empire ["Intergalactic Cruser"
"Destroyer"
"Im just making these up now"]}}}
You can extend the language and define your own constructs using Macros.
The first example of this you see is from Leiningen. The defproject
function is a macro that helps you easily define the configuration of a Clojure project.
An example of a macro that is part of the core Clojure language is defn
. When you define a function with defn
it is syntactic sugar for defining a thing that is a function.
(defn my-function [argument] (my-behaviour argument) )
(def my-function
(fn [argument] (my-behaviour argument)))
The following are the building blocks of Clojure, everything else is either a macro or a function
catch def do . finally fn if let loop new quote recur set! throw try
monitor-enter monitor-exit var