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.
So how do we read input in Clojure? Should be pretty easy? I thought so but didn’t find any example for reading in a loop so decided to write this blog.
So I am writing a program that simply echoes whatever user enters till the user enters the number 42. Got help here on this.
(doseq [input (take-while #(not= % "42") (repeatedly read-line))]
Let’s break down the above into smaller chunks to understand.
This just reads input from the standard input. There is some technicality that I am not going to cover. Ignore it for now.
repeatedly reads from the given function by calling it lazily. Note that. Lazily. Basically it will be lazy and won’t read anything till someone actually asks for it.
(take-while #(not= % "42") (repeatedly read-line)
take-while lazily gets the value from its second argument till some condition remains true. Here it reads from the standard input till input is not 42.
So what’s with the doseq? It makes sure that things don’t remain lazy. It’s the thing that tells that the lazy functions given above I need the result. It asks for the result. And then does something with the result. In this case it simply prints the number.
Let’s look at the various ways in which functions can be defined.
Defining an anonymous function can be done as below. The below defines a function which multiplies something with 3.
#(* % 3)
If you run the above in a REPL then you won’t see anything meaningful. To get something meaningful try something like
(map #(* % 3) [1 2 3])
You will get (3 6 9). How did it happen? Map takes a function and sequence as arguments and applies the function to all elements of seq and returns a list as result. Makes sense? No? Try to look at this.
Defining functions seems scary. Right? It’s not. There are easier ways to create functions in Clojure.
A simple way to define functions which just does nothing but returns a String is as below
(fn [a] (* a 3))
So why did I start with scary stuff? Because it’s useful sometimes when passing around and I like to be scary.
Clojure has a way to define multiple versions of functions like
( tmp "a")
([a] (str a))
You can call above with 0 or 1 arguments. It’s a nice way to do polymorphism.
Some languages have many ways to create and change Strings. Clojure keeps this simple.
;this is not a string
'NotString' ;Output is NotString'
;this is a String. note the double quotes
"I am a String"
;you cannot add strings to join them so the below won't work
(+ "str1" "str2") ;Exception
;this is the only way to join two strings
(str "hello" "world") ;"helloworld"
;you can have variables also in str function
;obviously as this is the only way to create strings
(def tmp "tmp")
(str "hello " tmp) ;"hello tmp"