C really is great for forcing people to understand what's going on. I really can't think of a better "low level" high-level language. But, once you know what's going on, it's not some huge penalty to move to a higher-level language as long as the machine code equivalent is predictable.
I know what a hash function is. I know what a linked list is. I know how trees work. And I know how vtables work. I also know that syscalls are orders-of-a-magnitude slower than most code.
Back in college, I took two SEMESTERS worth of finite element analysis. We took an entire first semester (senior year) just of math behind finite-element analysis and calculated them by hand. It wasn't till grad school, the second class, that we even got to USE the software. Why? Because the software lies. It was basically a year dedicated to how the software lies, and in what ways, and why... down to the mathematical basis for the failure.
99% of people aren't going to be ripping out paper equations in their daily work. But the point was, you should be able to if you need it to verify why the computer model is wrong.
The same applies to programming. I WANT to care more about high-level issues--the work I'm trying to get done--than the implementation. BUT, I want to know--with confidence--what my high-level code is going to end up under-the-hood.
Personally, I think languages haven't gotten high-level enough yet. I have no idea why it's possible to write code, but 99.9% of people and languages don't have a proper means of specifying static and dynamic RULES. Oh yeah, we can turn on a compiler option for warning you if you missed a return value. We can run a static or dynamic checker program that checks for "best practices". By why are we still, in 2017, unable to easily specify our own rules and practices and instead, we have "coding standards" and "review" to ensure those standards are followed. You know what computers are good at? CHECKING CODE VALIDITY. So why don't we have easily available, powerful toolchains for specifying custom, per-project standards on an AST-level? And further, why isn't the entire industry already using it?
I should be able to specify a list of commands that need to be called in order, and flag at compile-time if anyone writes code that fails to follow that order. Created an object but forgot to call an initializer? Forgot to load the TTF addon? Compile error.
(The closest I've ever found were GCC MELT (dear god, look at that webpage gore), and manually forking DScanner to add custom rules. I shouldn't have to learn the entire LISP language just to say, 'make sure X method gets called before Y for any object Z')
Everyone I talk to always skirts around the real issue. They say, "You should design API's so it's impossible to call them out-of-order." and "if coders don't follow guidelines you've got bigger problems." Bullcrap. Programmers are human and make mistakes proportional to the codebase size. The less requirements they have to keep in their head at one time, the less likely they forget one of those things. The more balls you try to juggle at once, the more likely one falls to the ground. And as for the API being impossible to call incorrectly? It must be nice living in perfect-world, where people have unlimited time and resources and there are no other requirements except "programmer can't call incorrectly". Oh look out that window, it's raining exceptions!
Now, with a good language like D (and much lesser extend C++), you can use templates and static if's to enforce rules. But it's the wrong tool for the job. You shouldn't be abusing templates to make SEMANTIC rules from INSIDE the language itself. You wouldn't write a bash script that checks itself for correctness. You should be able to write RULES the same way language designers do. You should be able to write a new attribute called "enforce_return" and stick it in your function signature and the compiler checks the return values for your homemade criteria. (or whatever your rules are.)
(e.g. Don't allow goto EXCEPT in this circumstance? That should be an AUTOMATED rule.)
We're programmers. We're supposed to automate things. But somehow, everyone is so used to the status quo, they automate everything... their VIM/emacs macros... their makefiles... their code... their unit testing... we'll even include vim tab and line-width macros into our files to ensure consistent indentation... but code standards? NO. That's that ONE THING is silly to automate! We'd rather stare at other people's code for hours during code reviews like an accountant without a calculator.
I mean, if you really sit back and let your mind wander at the possibilities, there are tons of useful things we could all do for any medium-sized project or larger. And even with small ones, it would force us to "write properly." Static and dynamic code analyzers already exist with "Best practices." Why not add our own practices to ensure we follow our own rules?
Any FOSS project of size has a coding standard that contributors have to follow to submit a patch. Allegro does. GCC does. The Linux kernel does. Automate it.