When I started learning Clojure the first and probably the biggest problem was to get started quickly. At that time I was following brave clojure to learn. I reached the part where we setup basic environment and then hit a roadblock. Everything was taking too much time to setup. I won’t go into all the stuff that happened but give you the short story.
Don’t go the Emacs way unless you know Emacs already. It is too much in the beginning. I wasn’t comfortable and spent time trying to learn Emacs instead of Clojure and got frustrated.
Option 1 (Beginner Level)
- Go to Light table website and download it.
Option 2 (If you are comfortable with Intellij Idea)
If you are reasonably comfortable with IntelliJIdea go through the 2 videos on vimeo on setting up cursive. It is better than Light table IMHO but might take a bit longer to set up.
Hope that this helps someone get started quicker than I was able to.
I recently came across recur in Clojure. It is a special form which allows for tail recursion in Clojure. If you have worked with Java you would know that JVM does not have tail recursion implemented due to all those stackoverflows that we face when using Java.
I had this code for summing the digits of a number repeatedly till I get a single digit which I wanted to improve so I asked for a code review
(defn sum-once [x]
#(Integer/parseInt (str %))
(seq (char-array x)))))
(defn sum-digits [x]
(let [y (sum-once x)]
(if (< y 10) y
(recur (str y)))))
I came to know about recur. Simply said we just replace the call of sum-digits inside sum-digits with recur and that’s it. Now instead of stacks Clojure does something else and we get optimized tail recursion which Java does not have.
It works with functions and loop. The loop docs is full of recur and that’s the only way to use loop.
To use recur we simply use it like a function call (like everything else in Clojure) with the exactly same number of arguments as the function or loop in which it is called.
Today we are going to look at generating the nth fibonacci number using case in Clojure. This seems to be familiar with Java’s switch case.
I wrote a function to calculate fibonacci numbers.
(defn fibonacci [x]
(+ (fibonacci (- x 1)) (fibonacci (- x 2)))))
Case takes x as an expression. Then we have constant-cases and result expressions. Here we have 1 and 2 as the constant-cases and 0 and 1 are the result expressions. In the end there is the option of supplying a default case which I am using for the fibonacci definition.
When using the above I quickly faced problems when trying to run it with bigger numbers. It becomes slow fastly. To take care of that we use memoize and +’ operator.
(+' (fibonacci (-' x 1)) (fibonacci (-' x 2)))))))
Here we changed fibonacci to be equal to a memoized function. Memoize keeps a cache of older results. This helps in the function not being called repeatedly. Also the addition operator was updated so that we can get bigint when needed.
It solves the problem of big numbers in case we call it with smaller numbers first. e.g call it with 100 then 200 then 300 and so on and it will give correct results. Obviously that’s a problem. Try and figure out how to solve it while I do the same 😀
Reduce is a very common thing in functional programming. In this post we will look at simple examples using reduce in Clojure
A simple example would be to use it to sum all elements in a sequence.
(reduce + [1 2 3])
By itself it is very simple but we can combine with other things. Like we can use it with map to find the length of a sequence
(reduce + (map (fn[x] 1) [1 2 3]))
Initially we use map to get a 1 for each element in the sequence and then we reduce it.
To sum all odd or even numbers in a list we can combine it with filtering
(reduce + (filter odd? [1 2 3]))
(reduce + (filter even? [1 2 3]))
So basically it is converting multiple values into one using some function. It applies the function supplied to first two elements in the sequence and uses their result with the third element and so forth.
But we can also supply a default value
(reduce + -2 [1 2 3])
Here -2 is a random default value that I chose. You can use any default. This will be used along with the first value.
Is the above not making sense about how it works? Try this in your REPL
(reduce println -2 [1 2 3])
This will print the sequence in which println is used. Hope this helps. You can check the docs for reduce but I found the explanation a bit less formatted so you can alternately read the PR that I submitted.