y = f(x);
I'm extremely terrified to what is going on. It is like looking into an abyss. Is this code calling a function named "f" with argument "x"? If so, there may be several different functions "f" depending on the type of "x". Maybe none of them has the same type as "x", but there are some conversions that may happen and lead to that. Or maybe "f" is not even a function, but it is an object that has overloaded the parenthesis operator? And then, what happens to the result, whatever type it has. Is it calling a copy constructor (over some inheritance chain)? Is the assignment operator overloaded? If running this line results in an execution error, I'm totally lost as to where to find the problem.On the contrary, in C, the same line says explicitly what code is executed, without need for further context. If the code compiles, there is a single visible definition of a function named "f" and this is the code that is called.
I read much more code than I write. But code with lots of abstractions, like C++ with objects or templates, however elegant was to write, is a disgusting chore to analyze, understand and eventually fix (because the abstractions always fail). On the other hand, analyzing C code is pretty straightforward, even if it was a bit more verbose to write.
Indeed and I think this is the root of all the internet shouting on abstraction-heavy languages vs procedural/"simple" languages. A lot of folks that think in abstraction find it tedious and unsafe to deal with detail-oriented languages, while folks who are more detail-oriented find the abstraction disorienting and unsafe in their own way. Given that one group can't do away with another group, I hope we can all learn to work together.
On the other hand, I tend to think in terms of abstractions. And thus find things much clearer when they are based on high level abstractions (things like map and filter, RAII, pattern matching, etc). And I like languages like Rust and TypeScript where I can express those. If I read a for-loop, I have to translate it into a more abstract higher-level function in my head to understand what it's doing anyway.