Style note: This series uses martial-arts/cultivation metaphors to tell the story of programming. This is an intentional choice by the author to make dry concepts more vivid. If you’re not used to it, be patient — the technical content remains accurate and complete.
At that time, the Western Programming World saw two late-stage YuanYing grandmasters at peak power, just half a step from breaking through to the HuaShen realm. One was the Turing Master — Alan Turing — renowned for his Turing Machine technique. The other was the Church Immortal, Alonzo Church, who roamed the three realms with the Lambda Calculus art.
Turing’s Turing Machine and Church’s Lambda Calculus are actually two approaches to the fundamental principles of computation, commonly referred to together as the Church-Turing Thesis.
The Turing Machine is grounded in maintaining state machines and process state, while the Lambda Calculus is built upon the properties of mathematical functions. At my current level of cultivation, I haven’t grasped such profound matters, so I dare not speculate here. I only know that these two techniques are the origin of the two most powerful schools in today’s programming world: Object-Oriented Programming and Functional Programming.
There are quite a few programming paradigms. OOP and Functional Programming are just two among them. In Peter Van Roy’s book “Programming Paradigms for Dummies: What Every Programmer Should Know,” he presents a comprehensive model of the relationships between paradigms:

In the history of technology, OOP seems to have held the advantage over Functional Programming. Just look around — from the moment you started coding, the world has been saturated with OOP rules. Job descriptions and interviews all mention OOP as a fundamental technique. Technical discussions mostly revolve around concepts like Class, Object, Inheritance, and at higher levels, SOLID, Polymorphism, Encapsulation…
But globally, from Lisp to FP, then Haskell, Elixir — there has never been a shortage of cultivators walking the Functional Programming path. Especially after 2010, for reasons unclear, people began complaining more about OOP, citing Joe Armstrong’s banana/gorilla argument more frequently, and the topic of “Functional Programming” started heating up again.
I first encountered Functional Programming around 2015 through a YouTube talk by “Uncle Bob,” but I didn’t quite get it, so I didn’t pay much attention.
It wasn’t until 2016 that I seriously dove into Functional Programming after reading two article series: “Composing Software” by Eric Elliott and “So You Want to be a Functional Programmer” by Charles Scalfani on Medium.
Eric Elliott explains each Functional Programming concept thoroughly and clearly. Charles Scalfani is a true FP fanatic. He presents it as a philosophical system, a distinctive worldview. Scalfani even elevates Functional Programming as an evolutionary step in the history of programming. His writing leaves an extremely strong impression.

Earlier, Scalfani also wrote “Goodbye, Object Oriented Programming,” which sparked heated debate.
But readers should note: Functional Programming doesn’t oppose OOP. They are merely different cultivation paths, both heading toward the Great Way. When coding, we can entirely combine multiple programming paradigms as long as we achieve Correct — Fast — Stable — Clean results.
ReactJS is a prime example — you could view it as 7 parts Functional Programming + 3 parts OOP. On this point, Anjana Vakil has an excellent talk at GOTO 2017.
In any case, since then, the Functional Programming mindset has continued to spread, influencing the design of countless modern programs. With just a little attention, we can recognize Functional Programming’s prominent characteristics in most frameworks and new language updates. Even concepts that seem unrelated at first glance — WebComponents, Serverless, Microservices — also carry echoes of Functional Programming thinking. And I’ve almost stopped touching class, new, and this altogether.

What is Functional Programming?
So what exactly is Functional Programming? If you Google it, you’ll find dozens of different explanations. I advocate a short definition:
Functional Programming is a programming method that takes functions as the basic unit of operation.
That’s right. In its ideal form, Functional Programming is just function, function, and function. No assignment statements, no need for variables, no holding global state. In Functional Programming, we control program flow by composing functions together. We juggle functions back and forth — receiving functions, returning functions, nesting, chaining, transforming them in every conceivable way.
That’s called “first-class functions” — a space where programmers treat functions as “first-class citizens.” Wherever functions are valued this way, we can program in the Functional Programming style. JavaScript, Python, Golang, and even PHP are like this. Java, starting from v8.0 released in 2017, is also like this. Though not as perfect as Haskell, F#, etc. — true cultivation realms born for Functional Programming — we can still practice Functional Programming…
We just have to adapt a bit, be more flexible a bit. That’s why in JavaScript and Python programs, even when writing in a Functional Programming style, we still need variables and assignment statements to operate.
Low-level cultivators wanting to begin the Functional Programming path need to grasp basic concepts like Immutability, Purity, Higher-order functions, Currying, Function Composition… After advancing to higher realms, they can explore Monad, Functor, Setoid, Idempotent, Lens… and many more.
Now, let’s begin the journey…
Immutability
Immutability means unchanging nature.
The first principle in Functional Programming is: once declared, it stays that way forever — never to change. Variables or objects in Functional Programming, if they exist, must be immutable.
This code is not Functional Programming because x and y change:
var x = 5;
var y = 2;
while (x < 10) {
y += x;
x++;
}
Mutability is the greatest taboo in Functional Programming. It must be minimized to the lowest possible level. Current coding conventions and best practices encourage using const for declarations, abandoning var entirely, and using let sparingly.
For Objects, use Object.freeze to lock all properties. You can also use Object.defineProperty or Object.defineProperties to lock specific important properties. These solutions only support one level of properties. You must actively code additional logic to apply them to nested properties.
If the project is sufficiently complex, consider using dedicated libraries like Immutable.js, Baobab…
Purity
Purity means pure, unadulterated, uncontaminated.
This is the second principle in Functional Programming: all functions must be pure functions — no side effects, no impacting any external values, and no modifying input parameters.
This function is not pure because it modifies an external DOM element and changes a value stored in localStorage:
const updateView = (html) => {
let $view = document.getElementById('panel');
$view.innerHTML = html;
localStorage.setItem('panelCache', html);
return $view;
};
Another important characteristic of pure functions is that for a given set of inputs, there is always one and only one corresponding output. This is the property of mathematical functions.
This function is not pure because it returns different results for the same input:
const getDuration = (timestamp) => {
return Date.now() - timestamp;
};
Pure functions in Functional Programming are usually short, simple, and handle only a single logical concern.
Here’s a classic pure function:
const add = (a, b) => {
return a + b;
};
No matter how many millions of times you call it, add(3, 2) always returns 5.
Writing unit tests for pure functions is as pleasant as strolling with an innocent, pure-hearted maiden!
Immutability and Purity are the two most fundamental characteristics of Functional Programming, distinguishing it from other programming paradigms. Cultivators on this path must hold the mindset of “immutable” and “pure” in every moment.
Comments