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"