I was considering to learn Lisp for a long time. The reason for this is that my lecturer Chris Stephenson had strong discourses on functional programming and he was using Racket (a Lisp dialect) in some of his classes. This led me to think of searching on Lisp programming language.
I read and watched the experiences of Lisp users on the Internet and the most interesting part of my research was the approaches of the users towards this language as if it was a kind of secret space technology.
The experiences of Paul Graham with Lisp and the fact that he wrote Hacker News site with a Lisp dialect (Arc) he invented aroused my curiosity.
I said “Okay. Now it is time to select a Lisp dialect.” I found the Clojure language among Lisp variants and I saw that it can run on JVM. Moreover, it was a platform that I was familiar with as a Java developer. The comments about the community were also very positive and I took the first step…
The Clojure language has a very plain and simple structure and the syntax is also very plain. For example:
(+ 1 2)
Open the brackets, write the name of the function to be called, the parameters and close the brackets; that’s all and now you know how to write Clojure. Let’s say the rest is a little detail. :)
The first version of Lisp written in 1958 used the same semantics as the current ones (mostly). In other words, there is no syntax evolution on different versions of language, such as Java (see Java 7/8). The core structure is very plain and simple and this is a nice detail into the language.
#2 Java Interoperability
The creator of the language Rich Hickey has a very pragmatic and strategic reason for writing Clojure on JVM. As it was written on JVM, Clojure gives access to all available Java (or any JVM language) libraries and their frameworks. So you can call Java code from Clojure code, or vice versa.
It should be considered that the languages written on JVM have such a great heritage and this is a huge advantage, especially for developing enterprise software.
In the following example, we check whether all of the String characters are in capital letters by using isUpperCase() method which is inside of Character class in Java:
(every? #(Character/isUpperCase %) “HELLO”)
#3 REPL (Read Eval Print Loop)
REPL is a secret weapon for Lisp programmers and it is a tool that enables you to interactively contact with the program you write and evolve it rapidly.
Discourses of REPL Driven Development never end in Clojure community and it has become quite popular. The reason for this is that you can productively and quickly write a code. The progresses such as finding a bug or adding/removing a feature can be easily carried out through quick feedbacks.
It is a dynamic language and there are very important advantages. For example, you built your web application, but then you noticed an error in the message that will be shown on the screen and change it (or did a more complex change); Clojure quickly changes the Java Bytecode and have the change we desire. This will save so much time.
If you have to make such a change via a language like Java, unfortunately you have to restart the application. (most of the time)
The biggest advantage of Clojure is that it can be so flexible and dynamic under a powerful system like JVM. It is dynamic and multi-threaded (unlike Python, Ruby) and it runs on JVM; what else do we want? :)
After I learnt the macro system of Lisp, I had a real enlightenment. The macro system provides you an opportunity to extend the language; you can think that you could add a feature into the language. In fact, a macro is kind of a function which produces function(s) for you, at compile time.
In other words, you can get rid of duplicate codes you don’t want by writing nice macros.
For example, let’s suppose we have a nested function thread as follows:
(if-let [a 1]
(if-let [b 2]
(if-let [c 3]
(+ a b c))))
Now as you well know, the code is not nice at all, but if I write a macro that will produce this code at the compile time with a more classy syntax, everything will be as I want.
Let’s write our macro called if-let*:
`(if-let* ~bindings ~then nil))
([bindings then else]
(if (seq bindings)
`(if-let [~(first bindings) ~(second bindings)]
(if-let* ~(vec (drop 2 bindings)) ~then ~else)
I know it looks very complicated, but I would like to show a macro example.
Now the nested code will be produced for me, but I will only write the following part:
(if-let* [a 1
(+ a b c))
Of course, there can be much more complex examples. I have the chance of decreasing code on a great scale and the honor of having clearer code through using macro in Clojure projects.
Java programmers know that try-with-resources feature is available in Java 7 version. Therefore, IO classes which are written in try() are automatically closed, when their progresses are finished. For example, a macro in Clojure called with-open settled this progress in the standard library.
Briefly, in Clojure, you don’t have to wait for minor changes on different versions as in the other languages (Java etc.). We can add these features by writing cool macros :)
The creator of the language worked mainly on concurrent systems for a long time and used a variety of languages such as Java, C#, and C++ while working. In his interviews, he talked about the difficulties of trying to write concurrent systems via these mutable languages and said that the main reason for this problem originates from that they are mutable by default.
In fact, Rich Hickey said that he wrote Clojure for himself. He developed the Clojure which is immutable by default for concurrent systems, because this work gets harder to be carried out due to this kind of difficulties (mutable data problems). The fact that immutable data will not change when it is sent to another thread so we don’t have to worry about the state of the data.
One of the biggest bet of Clojure is that it was designed in a manner that it makes writing concurrent programs easy and entertaining as well as provides an opportunity for a less amount of error at the same time.
Moreover, the language has 4 mutable reference types and this facilitates our work on state management issues.
Var: Local scope
Atom: Atomic field (like AtomicBoolean in Java)
Agent: Async programming (similar to the Actor system in Scala)
Ref: STM (Software Transaction Memory) ensures that the state of more than one variable can be changed in a coordinated manner and there won’t be any condition like deadlock. It has a similar structure to the database transactions.
When you work on frontend and backend, you use a single language and thus you have the advantage of motivation and time. So there is no any mental context switch, when you write React for frontend while writing Java on the server side.
Clojure and ClojureScript can share the same code (Reader Conditionals). Therefore, we write the code at once and use it on both frontend and server side. (Example usage: Validations)
I can say that these technologies provide nice opportunities for being a Full Stack developer.
Clojure community consists of really cute, helpful and generally senior and experienced ladies and gentlemen. Of course, it is not as big as the community of other languages. It has a modest, small and sympathetic volume, because it is a niche technology ecosystem.
As far as I’ve seen at the Clojure meetings in Berlin in which I constantly participate, I can say that the profile of Clojure users generally is a nice group of people consisting of chief scientists, mathematicians, and developers who have 10+ years of experience.
Clojure page of Reddit is a quite active formation and everybody easily asks whatever she/he wants and receives the answer.
If you read this until here without getting bored and if you want to give the language a little chance, I’ll share references for you to learn Clojure step by step.
- Brave True Book (free online version): https://www.braveclojure.com/clojure-for-the-brave-and-true/
- After reading Brave True, you can sign up 4Clojure class on Clojureacademy, which is the platform written by me: https://clojurecademy.com/courses/17592186045426/learn/overview
- IntelliJ IDEA Clojure Plugin: https://cursive-ide.com/
- For Emacs users: https://github.com/clojure-emacs/cider
- Joy Of Clojure book [Advanced] (also available on Safari): https://www.manning.com/books/the-joy-of-clojure-second-edition
Clojure completely changed my perspective on programming. I found myself as a more productive, faster and more motivated developer than I was before.
Such a situation arose that one Clojure programmer is able to carry out a work that can be done by 2–3 Java/alike programmers. (You can ask professional Clojure developers, they will agree with me. :))
As far as I know, there are currently 5/6 people who develop projects with “Clojure Developer” title in Turkey.
I hope this number will increase in Turkey in near future. Because I think it is the right technology for a lot of work and there is a need for diversity of programming languages to increase in our community.
Those who wonder can view open source Clojure projects developed by me from my GitHub page: https://github.com/ertugrulcetin