Wednesday, April 30, 2014

Pure functions with Clojure

For people coming from background in imperative languages such as C, C++, C#, Java, Python, PHP, Perl, PL SQL the idea of a pure function is hard to digest. There is also a category of programmers who confuse a procedure for a function. These people tend to think that after all writing the procedures for modularity is what functional programming is all about. Nothing can be further from truth. Especially intriguing are PL SQL old timers who distinguish between procedures and functions by saying that a procedure cannot have return value. As we will see in this short introduction, this is the definition of impure function - opposite of the hero of this movie. It would be really enlightening for everybody if they fully qualify what they are saying - they mean stored procedure when they say procedure.

What is a pure function?

A pure function is a block of code that does not change anything and has no side effects. Printing to a console, writing to a file, changing database rows, writing over a socket are all considered side effects. The most oft-asked question is why would anyone want to write a function like that. The answer is not hard to imagine. If a function cannot have side-effects then the only reason to write and call it would be the return value.
Another distinguishing feature of a pure function is that the output depends solely on the input parameters. So if you have a pure function, giving it input set {X} will always give you an output Y.
A pure function is modeled after functions in mathematics. So if we have a function that 'maps' an integer to its square we could write it as f(x) = x*x in one notation. This notation says that for every number x the function transforms it into x**x. When we call this function f we don't expect anything else to happen. Moreover, we expect the output to depend only on the input x and nothing else. For example we don't expect this function to update your MySQL database or write something over the socket. This is what pure functions strive to achieve.
A burning question that remains unanswered if all we have is pure functions then who is going to print to console and write to MySQL? The simple answer to that question is your non-functional blocks of code. A functional programming based solution is not a replacement for the 'traditional' Object oriented solution but is almost always a complement each other.

Why pure functions?

The prime reason to have pure functions especially for things like mathematical calculations is concurrency. This topic is important enough to warrant a post of its own, but suffice it to say that if a block of code has no state, it can be called simultaneously by more than one caller without getting into each others way.

Some examples

Let's look at some examples of pure functions written in Clojure
(defn purefn [] " Clojure is addictive")
(def helloWorld (fn [] "Hello world"))

These two functions are pretty much the same. The caller always gets a fixed string, no matter what else is happening in the outside world. Here is the output of an invocation on a REPL
user=> (helloWorld)
"Hello world"
user=> (purefn)
" Clojure is addictive"

Here is an example of impure function
(defn someRandom [] (rand 100))
The reason why someRandom would be categorized as impure function is that the output is not the same across various invocations. The function takes no input so if this were a pure function we would expect a constant output. Clearly this is not the case. For example-
user=> (someRandom)
84.42670022246767
user=> (someRandom)
18.165728504526957

No comments:

Post a Comment