After many years I returned to study Clojure, a few weeks ago. Some time ago a friend introduced me to this language with a very different paradigm than what I knew by working with imperative, object-oriented programming in C++, PHP and Python. At that time it was complex and frustrating for me to understand it, especially due to the little documentation that I had access to. Today, thanks to the greater information available, I returned to the task of approaching this paradigm of Functional Programming. I remember when I was at school someone told me once …
They say that when you are learning something new the best way to fix the concepts is to try to explain it to somebody else. And the best way to teach somebody is when you still remember how difficult it was when you didn’t know anything.
That is why today I decided together with my learning process to also create a series of mini tutorials with basic concepts to learn Clojure.
What is Clojure?
Functional programming is a declarative programming paradigm based on the use of mathematical functions, in contrast to imperative programming, which emphasizes state changes through the mutation of variables. Functional programming has its roots in the lambda calculus, a system formal developed in the 1930s to investigate the foundations of computation. It builds on the definition of functions and their application including recursion. It has a very small core without number primitives, yet has proven to be Turing-complete. Most functional programming languages are elaborations of the typed or untyped lambda calculus.
If you are interested in writing more robust programs, that are less susceptible to errors and expand your thinking; functional programming has a lot to offer to you. For example, the immutability minimizes the possibility of introducing accidental defects originating from the manipulation of the program state in unknown places, e.g. libraries. Immutability reduces complexity and allows to reason locally.
Another great reason to learn functional programming is to take advantage of parallelism. Writing parallel code in a functional paradigm language is very easy.
For some people, the mathematical origins of functional programming make this paradigm simpler to understand than object orientation. They build on the mathematical concept of functions, whenever they are called with the same parameter, the result will be the same, without anything else in the program universe changing. Of course this is not exclusive to functional programming, since we can achieving the same result in other paradigms, but functional programming will help you always think about building works without side effects and standardizes functional reasoning easy in all libraries.
NOTE: Some recommendation about Functional Programming:
- A beginner friendly intro to functional programming
- So You Want to be a Functional Programmer
- An Introduction to the basic principles of Functional Programming
What do I need to program in Clojure?
To program in Clojure the requirements are simple:
- Java JDK version 11 virtual machine (OpenJDK on most GNU / Linux systems) or later (and probably earlier, the JVM is very stable and backwards compatible).
- Leiningen (you can find the installation instructions at http://leiningen.org/)
Note: in one of the following tutorials I will explain the installation process of Clojure in detail.
To start working in Clojure, an acronym that will be common at all times is REPL (an acronym for read, evaluate, print and loop) which is an interpreter of the commands that we will be passing to it. If you are already a Ruby programmer, you may have already worked with irb or pry. Python also offers a tool for the same purpose. Scala and Erlang are examples of languages that also offer such tools by default.
The first step would be to open a console and type:
The first time it will take a while to execute Leiningen, since it will need to download some dependencies to start. In the interactive terminal message more or less like this should appear to you:
nREPL server started on port 59100 on host 127.0.0.1 - nrepl://127.0.0.1:59100
At this point our console is waiting for you to type some information:
This means that we can already write code! Try typing the following:
Pressing the Enter key (don’t forget the “”) we pass the instruction to the interpreter and it will return:
This seems to me the simplest way that exists to write the famous “Hello world” of any programming language.
If I get this far then why not try a couple more evaluations inside our REPL interpreter?
We are going to see some arithmetic expressions of Clojure to understand the syntax of it a little more. Type the following expression into the REPL and hit ENTER:
(+ 2 3)
The result, as you probably already saw, was
5, but the syntax seems very different from everything we know in other languages. While this looks crazy, it is a bug not a feature ;).
This line looks like a list (keep this concept in your memory, we will return to it at another time), made up of +, 1 and 2; Let’s look at the parts:
+ ==> Function (sum operator)
2 ==> 1st Argument
3 ==> 2nd Argument
It happens that the first item in this list is special. This element is the function that is executed, and the other elements in this list are arguments for this function.
The same can be found in other simple and complex arithmetic expressions:
(* 2 8)
;; Result 16
(- 6 3)
;; Result 3
Something a little more complex:
(- (* 10 9) 10)
;; Result 80
Here it would be important to introduce two concepts:
- In Clojure comments start with one or two semicolons: ;;
Everything behind this double score will be ignored by the interpreter. For example
;; We already know how to perform arithmetic operations in Clojure
- Expressions in Clojure always evaluate from the inside out in the same order of the arguments and respecting the precedence of the parentheses.
(- 10 (* 10 9))
;; Result -80
– ==> Function (subtraction operator)
10 ==> 1st Argument
(* 10 9) ==> 2nd Argument composed by the multiplication of 10 x 9
- First we do the multiplication 10 * 9 = 90
- Subsequently, the subtraction is performed 10 – 90 = -80
This example is where Clojure shows another difference syntactically. From the point of view of precedence, it is clear that the sum will be done first. The difference, however, is that the language requires parentheses, which leaves no doubt as to what precedes what and therefore, the order of execution of the code is always from the inside out.
NOTE: Actually expressions in any language are evaluated that way. If you write (10 – (10 * 9)) in Python then it will also evaluate from the inside out. It is the nature of composing expressions that has this inside out character. In many functional languages expressions can be sequentialized by let or monadic bindings.
It is here I hope that some first basic concepts of Clojure have become clearer to you.
Closing our interpreter
To close our REPL interpreter it will only be necessary to press
It is also possible to exit with the key combination control + d.
I hope you found this first tutorial interesting. I plan to publish more tutorials while I am learning Clojure. On the next post I will describe my experience installing Leiningen