The Dao of Immutability
The Way of the Functional Programmer
I was wandering the archives of an old library, and found a dark tunnel that led to the chamber of computation. There I found a scroll that seemed to have fallen on the floor, forgotten.
The scroll was encased in a dusty steel tube and labeled: “From the archives of The Church of Lambda.”
It was wrapped in a thin sheet of paper that read:
A master programmer and his apprentice sat in Turing meditation, contemplating the Lambda. The apprentice looked at the master and asked, “Master, you tell me to simplify, but programs are complex. Frameworks ease the work of creation by removing hard choices. Which is better, a class or a framework?”
The master programmer looked at his apprentice and asked, “did you not read the teachings of wise master Carmack?”, quoting…
“Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function.”
“But master,” the apprentice started — but the master interrupted, asking:
“Is it not true that the word for ‘not functional’ is ‘dysfunctional’?”
And then the apprentice understood.
On the back of the sheet was an index that seemed to refer to many books in the chamber of computation. I peeked inside the books, but they were filled with big words I did not understand, so I put them back and continued to read the scroll. I noticed that the margins of the index were filled with short commentary, which I will reproduce here, faithfully, along with the writing from the scroll:
Immutability: The true constant is change. Mutation hides change. Hidden change manifests chaos. Therefore, the wise embrace history.
If you have a dollar, and I give you another dollar, it does not change the fact that a moment ago you only had one dollar, and now you have two. Mutation attempts to erase history, but history cannot be truly erased. When the past is not preserved, it will come back to haunt you, manifesting as bugs in the program.
Separation: Logic is thought. Effects are action. Therefore the wise think before acting, and act only when the thinking is done.
If you try to perform effects and logic at the same time, you may create hidden side effects which cause bugs in the logic. Keep functions small. Do one thing at a time, and do it well.
Composition: All things in nature work in harmony. A tree cannot grow without water. A bird cannot fly without air. Therefore the wise mix ingredients together to make their soup taste better.
Plan for composition. Write functions whose outputs will naturally work as inputs to many other functions. Keep function signatures as simple as possible.
Conservation: Time is precious, and effort takes time. Therefore the wise reuse their tools as much as they can. The foolish create special tools for each new creation.
Type-specific functions can’t be reused for data of a different type. Wise programmers lift functions to work on many data types, or wrap data to make it look like what the function is expecting. Lists and items make great universal abstractions.
Flow: still waters are unsafe to drink. Food left alone will rot. The wise prosper because they let things flow.
[Editor’s note: The only illustration on the scroll was a row of different-looking ducks floating down a stream just above this verse. I have not reproduced the illustration because I don’t believe I could do it justice. Curiously, it was captioned:]
A list expressed over time is a stream.
[The corresponding note read:]
Shared objects and data fixtures can cause functions to interfere with each other. Threads competing for the same resources can trip each other up. A program can be reasoned about and outcomes predicted only when data flows freely through pure functions.
[Editor’s note: The scroll ended with this final verse, which had no commentary:]
Wisdom: The wise programmer understands the way before walking the path. Therefore the wise programmer is functional, while the unwise get lost in the jungle.
He enjoys a remote lifestyle with the most beautiful woman in the world.