The purpose of this blog series is to share my newly acquired knowledge here at Kaluza, in order to consolidate it, get feedback from experienced colleagues, and hopefully help other new starters with their own learning journey. To integrate into the Flows team, I am learning Clojure from the book “Clojure for the brave and true” and by pairing with my teammates. I am also learning how to write tests for my programs, and use platforms such as Kafka for event logging, Docker for app containerisation, and Kubernetes for container orchestration.
This first blog aims to give an introduction to Clojure, covering the following topics:
- What is Clojure?
- Why Clojure?
- Clojure and the JVM.
- The Clojure REPL.
What is Clojure?
“The Clojure language is a Lisp dialect with a functional emphasis whose syntax and semantics are independent of any implementation”.
There are a lot of terms in this sentence that can overwhelm a beginner, so let's go through them one by one. Lisp is the second oldest high-level programming language, and has brought about the evolution of several different dialects, one of which is Clojure. Functional programming refers to the model where a program is built by defining and calling functions, which return values and even other functions, rather than changing the state of the program. In functional programming, functions are treated as first class citizens, which means that they can be treated like other data structures of the language, and therefore we can perform operations on them or pass them as arguments to other functions. In addition, state isn’t modified and data is immutable, which means that rather than changing data, a new set of data is generated. Coming from an Object-Oriented Programming background, where state is changed and objects are mutable, this is a whole new world and I’m glad I discovered it!
Being a Lisp, means that Clojure is data-driven and offers flexibility because of the Lisp macros. Clojure macros allow the transformation of code by code (as if code were data!), and this is really powerful because it means that one can decide if and when any part is evaluated, and can define a syntax extension to the language by defining a new macro. Moreover, Clojure comes with all the benefits of functional programming, it is designed for concurrency, and last but not least, it runs on an established industry-standard platform, the JVM, that promises performance, security and stability.
Clojure and the JVM
Clojure is a hosted language that targets the Java Virtual Machine. Being hosted on the JVM, Clojure requires using Java objects for core functionality, and can take advantage of some useful Java libraries. But how does it work? Code in Clojure is compiled to JVM-bytecode by the Clojure compiler, which is an executable java archive file (.jar). Bytecode is machine-level language code and relies on an interpreter (such as the JVM). The bytecode is then read by the JVM, and is translated on the fly into machine code that can be executed by the CPU. The process of a running JVM translating bytecode to machine code is referred to as “just-in-time compilation”. Clojure running on the JVM means that we can run our Clojure app anywhere, on any machine that has Java installed.
The Clojure REPL
The read-eval-print-loop is an environment that allows us to instantly read inputs, evaluate them, and print the result. This is a great developer tool since it is useful for experimenting with code and interacting with a running program, thereby enabling a quick feedback cycle.
If you have any comments on the topics covered, or if there’s anything you wish you knew when you started with Clojure or functional programming that you feel like sharing, you’re welcome to get in touch with me. I hope you found some value in this post, and please keep an eye for the next blog posts, covering knowledge on Docker, Kubernetes, Kafka and more.