It isn't a question of aesthetics, the primary pragmatic issue with languages that have many features is how hard it can be to read a new code base. Tools like macros and traits can save you a lot of typing but when someone else comes into your code, it is much harder to come to terms with it than simpler languages like C or Go where the set of features can all be held in your head and the actual code is explicitly stated rather than generated by macros and generics and such.
This is a natural tradeoff in language design, do you deal with verbosity and boilerplate because the language has few features, or do you deal with the cognitive overhead of understanding all the features?
I find Rust extremely easy to read. In comparison, I was trying to read a Go codebase and found it hard to read. Of course, I've spent multiple years writing Rust and almost no time writing Go and I don't know the Go programming language at all. It was very easy to "learn" of course. But I didn't actually learn it given when I started reading code bases I was interested in I started to see weird things like
which I couldn't find an explanation for using normal means so I asked chatgpt and it told me it's an
"interface compliance check" "This line is a way of ensuring that a certain type (*ReplicaClient) implements a certain interface (litestream.ReplicaClient)."
For some reason this pattern was left out of the official documentation. Am I missing other patterns? I find Traits much easier to understand.
Also, like many others I give coding interviews and people writing Go always seem to run into null pointer errors. I'm not making that up. (I have no sample for Rust programmers)
I think there’s this concept in language theory that those speaking or writing strive for more complex concepts as it matches better their thoughts, while those receiving strive for more simplicity as it takes more energy to make sense of complex concepts (think about it as adapting the language to your audience).
But I think the main problem here is the famous debate of statically-typed languages vs dynamic ones. As statically-typed languages add more and more features to be more expressive, they have to work around the compiler limitations and create very bizarre syntaxes if they want to keep performance.
But maybe this is a tooling problem? What if we could see the code in a simpler way even if the actual code involves macros and templates?
Swift has just implemented macros that Xcode expand to show the generated code in a collapse/expand way, making it easy to understand what it does.
This. Being able to expand macros lets you learn what it does in context, and once you're more familiar with the abstraction it gives you the benefit of hiding the details and highlighting the moving parts within an otherwise static structure.
> C or Go where the set of features can all be held in your head and the actual code is explicitly stated rather than generated by macros and generics and such.
The C preprocessor is a Turing-complete, and a lot of C code abuses it to implements things a lot more complex that just "macros and generics and such".
Because of that C with a preprocessor literally has a infinite "set of features", a pretty big set of features almost garanteed to not fit anyone's head. I don't think you can call something with - both by it's own code and it's libraries code - arbitrary turing-complete preprocessing "understandable".
But when all the features of the language fit in your head, it usually means the code you're reading keep repeating itself lacking more convenient features (yes Go, I'm talking about your error handling).
The needs of our programs are complex, so in the end this complexity has to be somewhere, and it is either in the language itself, or in our code…
This is a natural tradeoff in language design, do you deal with verbosity and boilerplate because the language has few features, or do you deal with the cognitive overhead of understanding all the features?