I was heading home one evening down a back road. Much to my surprise, there was a big rig driving down the same small country road. I was immediately irritated by this. "Doesn't he know he can damage the road? It wasn't built for heavy loads. The roads are already bad." I wanted to stop him and tell him off. I quickly dismissed that idea for my own safety. Then I thought of reporting his route to the trucking company or even the Department of Transportation. But then I had a thought that made me decide to drop the whole thing: What if he knew precisely what he was doing? And despite appearances, what if it was actually a well-considered choice?
Back to dev
This particular thought occurred to me because I experience the same kind of push-back from commentators of my posts from time to time. Most of the time the comment seems to assume that the choices I made were due to lack basic knowledge or experience, and they decided to educate me in the correct way. However, I've been at this dev thing nearly 2 decades, and an avid learner the whole time. I certainly don't know everything and continue to accept learning through correction. But the basics... yeah, I got those.
There is often a good reason that I get corrections. Sometimes I make the "wrong" choice on purpose.
Here is an example from my post on Understanding the Fold Operation:
// F# let runChallenge someList = someList |> List.fold update init
This is the way I would write the function in my own code. However, Functional Programming 101 and DRY says I should have written the
runChallenge function like this.
// F# let runChallenge = List.fold update init
This isn't the first time I received a comment that I should have used the latter style. It is shorter and avoids declaring
someList only to immediately pass it through to another function. So why wouldn't I use it? Well, experience. We have an app in production for a couple of years now that is written completely in functional languages. In the process I have experimented with multiple ways of expressing problems. One of them being point-free style as in the second example.
Whenever I come back to point-free code a month later, I noticed that I always have to trace through the implementation. Defining only the function name
runChallenge doesn't tell me anything about it. Then point-free definitions usually mean the implementation uses a bit of function composition internally. All of that makes it unclear at a glance as to which types a function works with, and therefore what kind of behavior is happening.
It is also "fun" trying to explain point-free code to new developers. It reminds me vaguely of explaining Perl code which uses the
$_ variable implicitly. It is a source of confusion and questions. Whereas when the parameter is explicit, I had to type extra characters, but then I don't get a question about it.
Because of these experiences, I generally do not use point-free notation, even though it is the "right" choice on paper. It is simply not the best dev experience in practice (in F# at least). And I'm not the only one who thinks so. (FYI, the speaker is the creator of the F# language.)
There are always exceptions, right? One case for point-free is where I am intentionally making a terse DSL, such as for URL routing.
Ignorance vs Intention
Fortunately, people cannot hear/read my inner thoughts (maybe Google and FB have something in the works). But unfortunately, they also can't know whether I have made particular choices out of ignorance or well-considered intention. I think most people don't want to read articles that start with a list of assumptions or caveats, so I don't take the time in every article to explain. Consequently, I am not surprised when I receive corrective comments along this line, and I take time to explain at that point.
I suppose the point of this post, dear reader, is encourage you to consider the author and context of the post. Perhaps they have missed something obvious. (I certainly do at times.) Definitely ask questions if you are unsure. But perhaps also give them some benefit of the doubt. If a particular irritant is tangential to the point of the article, maybe it's not worth mentioning. I'm also talking to myself here.
As to the truck driver. I observed his driving behavior as I followed behind him. The way he was driving the truck around corners, it was clear that he was carrying a light load. Then I thought of his alternative routes. The main one was a busy 4-way stop. He probably would have had to wait until a car stopped far enough back for him to make a wide turn. Taking that route would have delayed everyone at the stop. So ultimately I decided that maybe the driver knew exactly what they were doing, and I gave them the benefit of the doubt.
Top comments (8)
I am not aware of point-free style being somehow the "right" choice. There are probably places where it can be helpful, but adding a bit of contextual information almost never hurts, and can certainly help! In my opinion, pushing point free can go from being a little bit dogmatic to outright bad, depending on the case. I've seen examples online of people really turning their code into knots just to achieve a point free expression. Why they want to do this makes no sense to me: One has to go through a lot of mental effort just to unwind it back into something comprehensible.
Overall your point in the article strikes me as reasonable, but that part just bugged me a bit.
I probably could have come up with a more universal example, but that was just my most recent experience. I agree with you that point free isn't necessarily the "right" choice, but many people seem to consider it so based on the feedback I received multiple times. So I wrote the article from the perspective of assuming their feedback is correct in that instance, but I still chose to do it differently based on other considerations.
Stephen Covey touches on this in his book "The 7 habits of highly effective people". He says that you should never judge strangers from what little thing you see them do. They are working on a different set of paradigms and experiences than you are. I think that is absolutely true but also very hard to live by.
Great post as usual, Kasey.
I think the situations you described were in no way bad choices, but the only problem is observers having different opinions or less information than the actor. I don't think it is possible to intentionally make wrong choices by definition, because at the point in time where you decide you always try to do the best (but sometimes you may regret it in hindsight).
Good point. I put a comment in the code snippet naming the language. I didn't want to tag the post with a specific language because it's more of a general observation.