Rex Kerr
2 min readJul 6, 2022

--

I can't speak for everyone, but personally I don't find this to be true. Different languages result in me writing substantially different numbers of bugs per feature. There are two causes: first, some bugs are just made difficult to impossible by virtue of language design; second, some logic errors are avoided when being able to work at a more appropriate level of abstraction for the problem. (If I don't know a language well then there is a third problem: clumsiness with that language. But I'm discounting that.)

In my own coding, I find Rust to yield substantially fewer bugs per feature than anything else. (I also find the Rust community to be more consistently bug-averse than any other community.) It isn't the most compactly expressive language ever, so that plays a factor also. But it's not just the productivity multiplier thing. If I don't have an established codebase to work from, I am more productive in Rust (per hour of my time) than almost anything else precisely because of the low bug count. I know how I can leverage the guarantees of the language to create robust abstractions that help me solve problems. (I am more productive in Scala than in Rust because of its greater expressiveness, and yes, there are usually a few more bugs per feature, but few enough so that I usually come out ahead even accounting for debugging etc..)

For other people, things could be different.

Regarding package combinations, all languages allow you to combine arbitrary packages...but I'm assuming you're meaning with duck-typing-like ability to change fundamentals under the hood and mix and match those?

This is one of the things that I find to sound wonderful in principle and be an astoundingly bad idea in practice precisely because all those unexpected combinations make for piles of unpredictable bugs.

"Hi, I thought carefully through all the edge cases, and now you're changing where all the edges are. Good luck!"

(Rust, admittedly, doesn't score all that well in combining functionality because its restriction that trait implementations must be (provably) unique requires you to merge functionality of different libraries by explicitly wrapping data in newtypes as a witness for the implementation you desire. Pretty clunky. But a good robust implementation of generics, especially if you have higher-kinded types available, makes mixing and matching safe and easy. Scala, for instance, does very well in this regard.)

--

--

Rex Kerr
Rex Kerr

Written by Rex Kerr

One who rejoices when everything is made as simple as possible, but no simpler. Sayer of things that may be wrong, but not so bad that they're not even wrong.

No responses yet