Demystifying Clojure

Racheal Mwatela
6 min readFeb 5, 2019

It’s been over a month since I started learning Clojure and if anyone tells you it’s a mind shift believe me it is! My purpose for this post is to help you make that shift and develop the mindset that can help you learn Clojure(or at least what is helping me).

Two weeks ago I started on a book Clojure for the brave and true by Daniel Higginbotham which was recommended to me by my mentor/supervisor. What I really love about the book is the comparison between ruby and Clojure syntax. I have a background in ruby, therefore, this came in handy in helping me familiarize with Clojure syntax.

A culture that I am adapting while going through the book is spending a maximum of one hour every day to learn. Not just read but internalize and practice. I then get to explain to my supervisor what I have learnt the previous day. It’s easy to learn and just keep it to yourself but you grasp even more when you can explain to someone else what you have understood. I also get clarity on concepts I never understood the day before and an opportunity to be corrected. Believe me, the language programmers use (assign, pass, call) is not a piece of cake! That too, I believe takes practice.

This takes me to my first topic, assigning variables.

We assign variables in almost all languages but in Clojure, we bind names to a value. Confused? Don’t worry, if it makes you feel better it took me about a month to understand just that!

Let’s take an example in ruby

assigning variables in ruby

You can make several assignments to one variable in ruby(technically, in other languages too).

Here is a Clojure example:

user=> (def first-name "awesome thang")
=> first-name
;;returns "awesome thang"

Thought you should know: name is a keyword, therefore, you can’t use it as a ‘variable’ /name hence the first-name

We could assign the ‘variable’ first-name to other values in Clojure like so

binding different values to a name in Clojure

but it will be super confusing and you may give up Clojure before you get to the best part!

So, we can proceed to….

DATA STRUCTURES!

According to Wikipedia, a data structure is a collection of data values, the relationships among them, and the functions or operations that can be applied to the data.

It’s how data is stored and organize so that it can be used by operations efficiently.

In Clojure, data structures are immutable. Meaning you can’t change the value

immutability in Clojure

In the example above, we bind a vector to my-flowers which will return the vector when called. We then add an element roses to the vector my-flowers using conj (we will learn about this function ahead). It will return a new vector containing our added element when called. Call my-flowers again and you will realize our initial vector is returned. That is immutability. You can read it’s importance here

With this in mind, we can move forward with data structures.

1. Numbers

Consists of integer,floats,ratios e.t.c

user=>(type 100)
java.lang.Long
user=> (type 1.2)
java.lang.Double
user=> (type 1/3)
clojure.lang.Ratio

Thought you should know: type returns the metadata of the value

2. String

String represents text.

user=> (str "I love tic-tacs!" " and sodas")
;;I love tic-tacs!and sodas

Thought you should know: str function is used to concatenate and we use double quotes for strings declaration.

3. Maps

denoted as {}

example of a string map

(def string-map {"a" 1 "b" 2 "c" 3})

example of a keymap(contains keyword and values)

(def key-map {:a 1 :b 2 :c 3})

We can use hash-map to create maps

user=> (hash-map :a "jane" :b "doe") 
{:b "doe", :a "jane"}

and sorted-map to create a sorted map according to keys

(sorted-map :b "jane" :a "doe")
{:a "doe", :b "jane"}

We use get and get-in to look up values in a map and a nested map respectively.

(get {:name "jane" :age "34"} :age)
;; "34"
(get-in {:ladies {:name "jane"}} [:ladies :name])
;; "jane"

Thought you should know: The keywords in a map have to be unique. You cannot repeat the same keyword example: using :name in the same map will return an error.

We can also use keywords to look up values like so:

(:age {:name "jane" :age "34"})
;; "34"

4. Vectors

Vectors are a collection of values which are 0-indexed

denoted as [] example [1 2 3]

we look up values in vectors using the index. Therefore it returns the element at the indexed position. For example

(get[1 2 3 4 5] 1)
;; 2

we return 2 because it’s the 1st index in the vector.

Thought you should know: Vectors can be of any type and you can mix them up.Example:

(get [1 "lala lila" true] 2)
;; true

vectors are created using vector

(vector 1 2 3 4)
;; [1 2 3 4]

conj and cons are functions used to add elements to a vector

using conj and cons to add elements in a vector

notice the difference? conj adds an element at the end of the vector and cons add it at the beginning. Cool huh?!

5. List

List is almost similar to vectors except you can’t use get to get elements.

The basic syntax of a list is:

`(1 2 3 4 5)
(1 2 3 4 5)

We use nth to retrieve elements in a collection.

user=> (nth `(1 2 3 4 5) 2)
3

We can create lists using list

user=> (list 254 255 256)
(254 255 256)

List elements can also be of any type just like in vector. We also add elements using conj and cons in lists. They both add elements at the beginning of the list.

user=> (cons 4 '(1 2 3))
(4 1 2 3)
user=> (conj '(1 2 3) 4)
(4 1 2 3)

6. Sets

I never knew how important sets were till I started implementing them on my code and challenges. Set in Clojure is a collection of unique values.

There are two types of sets: hash-set and sorted-set

user=> (hash-set 1 2 3)
#{1 3 2}
user=> (sorted-set 1 2 3)
#{1 2 3}

As defined what sets are, we can have multiple similar elements but only one unique element will be returned. Example:

user=> (sorted-set 1 1 1 2 2 3 3)
#{1 2 3}

We use conj to add an item to a set

user=> (conj #{1 2 3} 4)
#{1 4 3 2}

When you add an element which already exists in a set, the set will contain only one of that value.

user=> (conj #{1 2 3} 3)
#{1 3 2}

We use set to create a set from vectors and lists

user=> (set `(1 2 3))
#{1 3 2}
user=> (set [1 2 3])
#{1 3 2}

To check values in a set, we use contains? , get and using a keyword as a function.

;; using contain returns a true or false value.user=> (contains? #{1 2 3 4 5} 4)
true
user=> (contains? #{"cat" "dog" "parrot" "fish"} "cat")
true
;; using get
user=> (get #{"cat" "dog" "parrot" "fish"} "fish")
"fish"
;; using the keyword
user=> (:fname #{:fname :lname :sname})
:fname

And that is it!

I also found these articles to be very helpful in understanding Clojure and I frequently refer to them:

https://learnxinyminutes.com/docs/clojure

Hope you enjoyed this and happy coding!😉🙂

--

--

Racheal Mwatela

Hey, I am a Software Engineer with a passion for mentorship and career development