PurelyFunctional.tv Newsletter 416: Why do we program in hard mode?
Sign up for weekly Clojure tips, software design, and a Clojure coding challenge.
Design Tip 💡
Why do we program in hard mode?
Sometimes one simple visualization can really blow minds. I am always on the lookout for them. I want to tell you about a recent one.
I was watching The Forgotten Art of Structured Programming by Kevlin Henney. He had a slide in it that really showed how crazy the industry is. Let's build it up one step at a time.
First, we draw two spectra. Mutable vs immutable data vertically, and shared vs unshared data horizontally. That create four quadrants.
Let's look at the easy quadrant. If we have immutable data that is not shared between threads, it's real easy. There can't be any problems.
Less easy is using mutable data. But as long as it's unshared between different threads, it's hard to get into race conditions.
If we want to share data, if it's immutable, there's no problem with race conditions.
So far, 3/4 quadrants are easy to work with. You know it's coming, though. The fourth quadrant has shared, mutable state. And it's the hardest possible way to work.
Of course, this is the de facto way programming languages work these days. I'm preaching to the choir, since you're a functional programmer, and what's more you're into Clojure. But it's just insane that the industry chooses to work in the hardest possible quadrant.
Just to dig it in a little more: the default for the industry is mutable data by default. And the other default is sharing that mutable data between threads. How much ink is spilled about how to make a class thread safe? And how hard is it to actually make it safe. There are three other quadrants to choose from, and the industry chose the hard one.
Like I said before, you're converted. I've been converted a long time. I've known about the dangers of shared, mutable state for a long time. But I've never seen this quadrant before, and how it paints a perfect picture of how nuts the industry is.
Defaults are great. In Clojure, the default is immutable, shared state. But you need mutable state. And you need to share it. Sometimes. Clojure shows how infrequent it is. And it give you tools for making the journey into that unsafe quadrant with equipment that can make you successful. I'm talking about the Clojure concurrency primitives. They make it easy to get shared, mutable state right.
Clojure isn't the only language. It's basically the playbook of most functional languages these days. And this is where I think functional programming isn't as self-aware as it should be. We often say "Functional programming is about immutable data." That's somewhat true. But really, I think the picture is more sophisticated than that.
Functional programming languages choose to make the default easy. It's a brave choice in an insane industry. But it should be an easy choice. Where functional programming really shines is in giving you tools for dealing with shared, mutable state. We're the only paradigm brave enough to address the problem. Functional programming is actually more about dealing with mutable state (and other side effects) than it is about avoiding mutable state and side effects.
That's the approach I take in my book, Grokking Simplicity. Is functional programming about shared, mutable state and side effects? Yes. We, functional programmers, are the only ones talking about them. And we have great tools for dealing with them.
Quarantine update 😷
I know a lot of people are going through tougher times than I am. If you, for any reason, can't afford my courses, and you think the courses will help you, please hit reply and I will set you up. It's a small gesture I can make, but it might help.
I don't want to shame you or anybody that we should be using this time to work on our skills. The number one priority is your health and safety. I know I haven't been able to work very much, let alone learn some new skill. But if learning Clojure is important to you, and you can't afford it, just hit reply and I'll set you up. Keeping busy can keep us sane.
Also, if you just want to subscribe for a paid membership, I have opened them back up for the moment. Register here.
Stay healthy. Wash your hands. Wear a mask. Take care of loved ones.
Clojure Challenge 🤔
Last issue's challenge
- Pattern matching - submissions
Please do participate in the discussion at the submission links above. It's active and it's a great way to get comments on your code.
This week's challenge
Clojure already has a function called
filter. You pass it a predicate
and it calls the predicate on each element. But what it doesn't have is
a function called
filter-index that calls a predicate on the indexes
of the sequence to decide what to keep.
;; keep even-indexed elements (filter-index even? "abcdefg") ;=> (\a \c \e \g) ;; keep prime-number indexes (filter-index prime? "abcdefghijk") ;=> (\c \d \f \h)
Thanks to this site for the challenge idea where it is considered Hard in Python. The problem has been modified from the original.
Please submit your design process as comments to this gist. Discussion is welcome.