Clojure-snips: How to get started quickly in Clojure?


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.

Beware

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.
  • Watch the getting started. You don’t need to watch everything. Ignore the videos on Javascript, Python and watch videos/read in sequence till (including) Instarepl. That way you can get started very fast.

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.

Clojure-snips: Tail recursion in Clojure


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]
  (reduce +
          (map
            #(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.

Clojure-snips: Fibonacci numbers using case and memoize in Clojure


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]
  (case x
    1 0
    2 1
    (+ (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.

(def fibonacci
  (memoize
    (fn [x]
      (case x
        1 0
        2 1
        (+' (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 😀

Clojure-snips: Using reduce with sequences in Clojure


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.

Clojure-snips: How to read user input in Clojure?


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))]
  (println input))

Let’s break down the above into smaller chunks to understand.

read-line

This just reads input from the standard input. There is some technicality that I am not going to cover. Ignore it for now.

(repeatedly read-line)

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.

Clojure-snips: Defining Functions in Clojure


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

(defn tmp
  ([] tmp "a")
  ([a] (str a))
  )

You can call above with 0 or 1 arguments. It’s a nice way to do polymorphism.

Clojure-snips: Strings in Clojure


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"

Clojure-snips: Equality in Clojure


Clojure allows you to test for equality using the equals(=) sign.

;you can compare two things
(= 1 1) ;true

;you can compare multiple things
(= 1 1 1) ;true 

;if any of them are not equal then we get false
(= 1 1 2) ;false

;if something is not strictly equal then we get false
(= 2 2.0) ;false

;but we can also check for loose equality (Notice two equals)
(== 2 2.0) ;true

;and it's not just numbers that can be compared
;see? didn't need anything special for strings
(= "abc" (str "a" "b" "c")) ;true

;nil (other languages call it null) can be compared the same way
(= nil nil)

Writing about Clojure


It’s been a while since I wrote on this blog. Been busy in many things. Recently I decided to start learning Clojure. I thought the best way to keep at it would be to start writing about it. So I decided that I am going to start writing posts every now and then about anything I learn in Clojure.  Inspired by Groovy Goodness I’ll try to work on “Clojure-snips”. Hopefully I will improve with time as I learn Clojure.

Getting Started

Clojure features

I’ll also keep a list of references here. Whatever I referred or helped me in learning Clojure.

Managing bookmarks becoming easier


I had mentioned last month that I am working on a bookmarker. Yeah I am still working and it is progressing. The search page is ready. I am using a work-around for adding the bookmarks and categories till the bookmark add page is ready. But I am happy with the work so far as it is becoming what I wanted although a bit slower due to lack of time. Here are some screenshots of working search page.

The search box has an autocomplete for giving suggestions for categories. It will give suggestions as per added categories. Pressing up down keys lets you navigate the categories and when you press enter the category is added on the page alongwith all bookmarks.

Below are some screenshots.

 

search-1 search-2 search-3

 

There is currently not much bookmarks added so only two categories came in autocomplete for search and one bookmark was added when category was chosen.

I forgot to mention earlier that the little cross in red lets you delete the category and the bookmarks tagged with the category. Obviously needed.