Learning Clojure: Day 2

Abid Uzair
Clojure Days
Published in
3 min readNov 23, 2017

I learnt some really cool concepts about data structures in Clojure. We have Numbers, Strings, Maps, Keywords, Sets, Vectors, and Lists. All the data structures are immutable.

Some key points to take away:

  • Clojure does not allow string interpolation as in case of format specifier in printf in C language. It only allows string concatenation using str function.
  • Maps are similar to dictionaries in Python where you have key-value pairs. It supports nested-maps also.
;; example of maps
user => (def my-name {:firstName "Abid" :lastName "Uzair"})
user => (println my-name)
;; => {:firstName "Abid" :lastName "Uzair"}
;; to retrieve value of firstName
user => (get my-name :firstName)
;; => "Abid"
;; You can also get value by simply doing,
user => (:firstName my-name)
;; => "Abid"
;; You can also set default return value in case a keyword doesn't ;; exist
user => (get my-name :fullName "keyword absent")
;; =>"keyword absent"
;; Nested maps
user => (def my-nest {:name my-name :location {:city "Hyderabad" user => :country "India"}})
user => (println my-nest)
;; => {:name my-name :location {:city "Hyderabad" user => :country ;; => "India"}}
;; use get-in to lookup values in nested maps
user => (get-in my-nest [:location :city])
;; => "Hyderabad"
  • Vectors are defined like arrays in Clojure. You can still use get function with vectors like maps.

You can add elements to the end of the vector using conj function.

user => (def primes(vector 2 3 5 7))
user => (println primes)
;; => [2 3 5 7]
;; Adding elements
user => (conj primes 11)
;; => [2 3 5 7 11]
;; Now print the same vector primes, you will get output as:
;; => [2 3 5 7]
;; Remember data structures in Clojure are IMMUTABLE!
  • Lists are very similar to vectors except that you cannot use get function to retrieve elements, instead we use nth function. And conj function adds elements to the beginning of the list.
;; Creating a list (Not to forget the apostrophe)
user => (def even-stevens '(2 4 6 8 10))
user => (even-stevens)
;; => (2 4 5 8 10)
;; Retrieving element using nth function
user => (nth even-stevens 3)
;; => 8
;; You can use default value like in get to prevent
;; IndexOutOfBoundsException
;; Adding element to beginning of the list using conj
user => (conj even-stevens 0)
;; => (0 2 4 6 8 10)

Interesting points :

  • It’s good to know that using nth to retrieve an element from a list is slower than using getto retrieve an element from a vector. This is because Clojure has to traverse all n elements of a list to get to the nth, whereas it only takes a few hops at most to access a vector element by its index.
  • When should you use a list and when should you use a vector? A good rule of thumb is that if you need to easily add items to the beginning of a sequence or if you’re writing a macro, you should use a list. Otherwise, you should use a vector.
  • Sets are collection of unique values. You can create sets from existing vectors or lists using set function.
  • contains? function is used for checking set membership. It returns true or false depending on whether the element exists or not.
;; creating a set datastructure
user=> (def vowels #{"a" "e" "i" "o" "u"})
#'user/vowels
user=> vowels
#{"e" "a" "i" "u" "o"}
;; creating a set from a vector
user=> (set [2 3 3])
#{3 2}
;; Note that it removes the duplicates
;; contains? function in sets
user=> (contains? vowels "a")
true
user=> (contains? vowels "b")
false

I learnt few concepts of Functions as well which I will be discussing in the next article since this one got really long. Lastly, I would like to share Clojure philosophy on simplicity.

It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.
—Alan Perlis

Source: Chapter 3 Do Things: A Clojure Crash Course

Thanks for reading!

--

--

Abid Uzair
Clojure Days

Currently empowering the person closest to me. Long term plan is to bend the universe for good. Kinda like changing the world one person at a time.