Following some in-person chats on a number of concepts of functional programming, my team pushed me to try to share and present some of these to a wider audience. Admittedly, finding online resources on FP that are both palatable and reasonably sized is not always easy. This article was written in December 2015 and was my best attempt—in my own perspective and with my own analogies—to talk about what lies beyond the obscure term monad by starting with functors.
The following is a continuation of last week’s post, wherein I extract some teachings from my experience in a distributed company such as Automattic.
Our brains didn’t evolve to operate like machines. Machines are predictable and togglable systems. They are especially suitable for 9–5 operation, whereas our brains are not. Continue reading “A panel on distributed work, pt. 2”
Last week I was a guest in a Q&A session in Lisbon about remote work. I would be speaking about my experience accrued over my years at Automattic. My co-guest was Pedro Moreira da Silva, a fellow Lisboeta working at GitLab, also a distributed company. Leading the panel was Malik Piara from Upframe. What follows are some takeaways from that session.
A couple of premises
It’s easy to forget that these exist when they’ve been the basis for your mental framework for a long time, and it struck me that they hadn’t been laid out properly at the onset of the Q&A.
Continue reading “A panel on distributed work”
I was asked why one should prefer
Here’s an analogy: why do we, as a talking species, use different layers of vocabulary? Why do we have abstract terms in our language, as opposed to only concrete terms drawn from tangible things from our physical world? I mean, the Romans did fine without abstract language, right? Or were they limited by Latin? Wasn’t the incredible boom of philosophical thought during the Enlightenment facilitated by the abstraction powers of the German language?
Here’s a different frame: why do we have programming languages of a higher level than Assembly? What’s wrong with
CMP AL,10; JNZ loc?
map and friends are more precise, sophisticated ways to talk about consistent patterns in data manipulation. Using them over
for is analogous to using the word “cake” instead of “the kind of food that you make by whipping egg whites and maybe adding sugar”. Interestingly, you can eventually add new layers of category on top of established layers: just like saying that butter cakes constitute a specific family of cakes, one could say that
pluck is a specialization of
for can still be useful, just like
goto is not necessarily the devil (we still use
switch, which is a
goto in disguise). It’s just very low-level, and for most scenarios we have well-known higher-level terms. Just as we are continuously taught vocabulary and expression over the course of our school years (and hopefully beyond that) to improve our communication skills (as speakers and as listeners), together we can and should aim to develop the fineness of our expression as programmers.
Caveat: yes, there is such a thing as too much abstract language, or a language too sophisticated, and it is important that speakers adjust their discourse to the expected reader. Just like in natural languages. But if our primary purpose in any given project is to develop quality products with quality codebases, we can raise the requirements in terms of language comprehension — within reason.
OK, but that’s all theory. If both
map are used with an inlined callback, pragmatically speaking, how do they represent a different level of abstraction? To trained eyes, they pretty much look the same, and neither forces me to avoid side effects.
filter you are intentionally limiting your power. You establish a contract, wherein you say:
- you’re not going to mutate the collection;
- (in the case of
map) you’re going to return a collection with the same size and with data derived from the original collection’s individual items;
- (in the case of
filter) you’re going to return a subset of the original collection, preserving the items and the order.
These important statements are part of the abstraction. As for the side effects:
filterprevent you from yielding side effects by default, whereas the default with
foris to mutate, unless you have an additional statement to create a new empty collection beforehand;
forinherently requires more noise to be added, as you need to set up the conditions of the loop and handle the iterating variable. Noise dilutes intent. Noise also makes it easier for mistakes to slip through. Anything from a misspelled
array.lenght, to a rogue comma or an illogical condition — ultimately, those are technicalities that you didn’t actually need to care about in the first place, yet they lead to pesky bugs creeping in.
Stock photography: Annie Spratt
“Detecting errors and doing something about them is a really important part of programming that we typically don’t teach much about in school. Since C is designed to avoid sweeping these problems under the rug, a C class is a great place to get students started on the right track.”
The reason behind “how did we get here” […] is that the people who are regulating the Internet have mistaken the Internet — in this case — for a newspaper delivery service. And sometimes we get really dumb policies that mistake the Internet for a video-on-demand service, and sometimes for a jihadi recruiting tool, and sometimes for a pornography distribution system — and it is all of those things, because the Internet is the nervous system of the 21st century.
— Cory Doctorow at a #SaveTheLink live Q&A.
Hossein Derakhshan, known as Iran’s Blogfather, warns of the ongoing cultural changes regarding the Web:
The stream, mobile applications, and moving images all show a departure from a books-internet toward a television-internet. We seem to have gone from a non-linear mode of communication – nodes and networks and links – toward one that is linear, passive, programmed and inward-looking.
Sometimes I think maybe I’m becoming too strict as I age. Maybe this is all a natural evolution of a technology. But I can’t close my eyes to what’s happening: a loss of intellectual power and diversity. In the past, the web was powerful and serious enough to land me in jail. Today it feels like little more than entertainment. So much that even Iran doesn’t take some – Instagram, for instance – serious enough to block.
“You might think, well that’s just common sense. But last I checked, computers don’t have common sense. Indeed, they must have a formal way to automate these kind of code optimizations. Maths has a way of formalizing the intuitive, which is helpful amidst the rigid terrain of computer logic.”
— Mostly Adequate Guide to Functional Programming on Wadler’s free theorems
The political and societal crisis currently sweeping the European Union is a topic I try not to get into here, as it touches and inflames bad things in me.
To be clear: I call it a political and societal crisis because that’s what it is. As Maslow said, “I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail.” What, then, should one expect, when one is run by finance, corporations, the nonelected, and generally compromised institutions and politicians of selfish neoliberal ideologies?
Before I get too caught up in this, here it is:
What is happening in Greece frightens many. A proper democratic process, by nature, threatens power structures in place. As power seeks to perpetuate itself, any attempt at democracy must be promptly squashed, by any and all means available. A result of this is the campaign of terror waged in Greece and across the Union.
Yesterday, the people of Greece firmly said όχι, which in my book translates to dignity. It isn’t a vote of ignorance, of vain delusions, or of irresponsibility; it is a resolute and proud acknowledgment of the challenges they face and the utmost expression of a nation’s desire for democracy and sovereignty.
I have nothing but the highest respect for the citizens of Hellen.
I recently had a conversation at work on possible coding advice, that quickly diverged into a matter of what I feel is code that speaks for itself vs. code that is ridden with comments because it can’t live on its own.
I tried to illustrate my point by defending some practices on clarity, which really are just a repackaging of common ideas from the world of “functional” programming — adopting recognizable patterns via higher-level functions, aiming for declarative code, centered around data transformations, etc. — in contrast with what I’d consider traditional imperative code — longer methods built around statements, more (and explicit) branching, mutable data and variable reassignments, etc.
My colleague then rightfully remarked that, while
filter et al. can be used to make things clearer, they can be abused, and chaining a bunch of these can lead to monstrous spaghetti just as badly as more traditionally imperative code. Similarly, list comprehensions can be nice and concise, but don’t really scale. That got us to try to generalize, which lead to my commenting:
I agree that “functional” code, in itself, isn’t immune to spaghettitis. I think the key here is really to keep functions small and as strongly specified as possible, so that 1) one can easily inspect them and understand what piece they represent in the larger chain of data transformations, and 2) anyone can think of them as black boxes (by trusting their specification; not specific to functional, but usually easier, especially with referential transparency) as they are called within a chain of manipulations elsewhere in the code.
In a way, maybe the root of all evil is just about anything we can call a “long anonymous chain of things”. So a long sequence of function compositions in one statement is bad, the same way a long sequence of rules within a list comprehension is bad, the same way a long sequence of statements within a procedure is bad. I added the term “anonymous” in there because I think the naming plays an essential role in the way we can break things down and grasp them. That is why my initial functional example [see below] defined
isPopularseparately, and it’s why a procedure might be defined in “paragraphs”, where each revolves around a variable or a helper.