Intro
I first encountered Clojure in 2017 when I was taking a Zenius course to prepare for my university entrance exam. I found a video playlist on YouTube, created by a Math and Physics mentor, Sabda PS. I was so curious: 'What kind of language is this?' I'd never heard of it before, so I clicked on the videos and found something strange. The syntax was so different from most popular programming languages. The language consisted of functions and data. It's like purely solving math functions, but with lots of brackets.
It didn't feel like I was just giving the computer instructions, it was more like I was simply telling it what I wanted to happen. That was totally different from how I usually solved problems. So, instead of focusing on instructions, I could focus on what I expected.
What is Functional Programming and what is Clojure?
There are several paradigms for code. These include functional programming, object-oriented programming, and imperative programming. Functional programming is a way of writing code that focuses on actions, not changing things. Imagine cooking: instead of altering ingredients in a pot, you always create a brand-new dish at each step. This helps your code be more predictable and clear, just like making a brand-new dish each time.
The Clojure is programming language that use functional programming paradigm like Haskell, Elixir, Common Lisp, etc. It's leverage the Lisp syntax. Here is the example of Clojure's hello world.
(println "Hello, World!")
Since it's a Lisp, Clojure always uses an opening parenthesis ( at the beginning and a closing parenthesis ) at the end for its expressions.
Why I love functional language?
I used to think hard problems needed complicated code. This often made my code big and messy, full of tricky parts that changed all the time. But learning functional programming changed my mind. It made things simple by keeping data from changing and making functions do one clear job.
Instead of trying to control lots of moving parts, I started building small, strong functions that just changed data from one form to another. This new way of coding didn't just make my programs simpler; it made programming fun again. It felt less like fighting with a computer and more like building something smart and neat.
The functional way of programming is a lot like doing math. Instead of telling the computer exactly what to do step-by-step and changing things as you go, you describe what you want by defining how inputs turn into outputs. Think of it like solving an equation: you put numbers in, and you always get the same answer out, without anything else changing. Each part of your code is like a math function that takes something in and gives something new back. This makes your code clearer, easier to understand, and more predictable, just like how math problems have consistent solutions.
Each part of your code is like a math function that takes something in and gives something new back. For example, consider a simple mathematical function like f(x)=x2.
- Input: You give it a number, say x=5.
- Process: The function squares that number.
- Output: It always gives you 25.
No matter when or where you call f(5), it will always return 25. It doesn't remember previous calculations or change anything outside of itself.
In functional programming, you write code that behaves the same way. A function that calculates the square of a number in a functional language would look very similar in its behavior:
(defn square [x]
(* x x))
- Input: You call (square 5).
- Process: The function multiplies x by x.
- Output: It always returns 25.
Let's see another example of calculating the volume of a sphere to further illustrate this. In mathematics, the formula for the volume of a sphere is:
V=3/4πr^3
You give it one input (the radius, r), and it always gives you back one, and only one, output (the volume, V). It doesn't matter when or where you calculate it; if you put in the same radius, you'll always get the same volume.
In functional programming, you'd create a function that mirrors this mathematical relationship. For example, in a language like Clojure, it might look something like this:
(defn calculate-sphere-volume [radius]
(* (/ 4 3) Math/PI (* radius radius radius)))
- defn is how you define a function.
- calculate-sphere-volume is the name of our function.
- [radius] means this function takes one input, which we'll call radius.
- ( (/ 4 3) Math/PI ( radius radius radius)) is the "recipe" for the output. It says: multiply 4/3 by PI and then by radius multiplied by itself three times.
Conclusion
Functional programming, and particularly my journey with Clojure, completely reshaped how I approach problem-solving in code. It taught me to see programming less as a series of instructions to a machine and more as the composition of mathematical functions. Just like how you solve an equation where f(x)=x2 always yields the same, predictable result for a given input, functional programming encourages building software with pure functions that are reliable, isolated, and free from surprising side effects.
This shift to a more declarative mindset, focusing on what I want to achieve rather than how to meticulously manage every step. Made my code simpler, more robust, and significantly easier to reason about. It unlocked a powerful way to handle complexity, especially when dealing with concurrency, by embracing immutability and reducing the moving parts. In essence, functional programming felt less like battling with my code and more like elegantly solving a puzzle, leading to a profound and enjoyable transformation in my coding paradigm.