Lately I have been thinking that we are getting the abstraction wrong in programming.

In real world, abstraction is a lossy process. From "white horse" to "horse", we lose the information about color. And this lossy nature of abstraction is important, as it become simpler. This should be differentiated from saying "horse" but actually meant "white horse", because in that situation, it is not abstraction but omission. The complexity is still there (or even more).

In programming, add types or mutability increase the complexity. In that regard, Rust is simply more complex. But that is not what I commenting on. I am commenting on the trend in programing to hide that complexity by omission (such as type inference) or make it implicit such as using key word 'let' and 'var'. They only make the user less aware of the complexity at surface.

Now I am not saying language designers are not doing the best they can do (earn both honest and popular credits); but I have been thinking what might be the ideal way to handle complexity, and I only can see how we are doing it with our natural language. In our day to day business, when we say horse, we do not care about its color, and any one who interprets the sentence (with horse) is fine to imagine either a white horse or black horse or any but need understand the color is not important. So in analogy, in high level abstraction, we should be allowed to say a number with no type but be understood by the compiler that any number will do, which may even include a byte. Then the language should allow us to declare specific type as well -- just like in real life we should be able to directly say "white horse" if the color is meant to be important. Which means we should be able to specify an integer with 64 bytes long (I don't think we ever really need arbitrary precision) if we deem critical. We should note that I am not referring a dynamic type, nor an optional type system. The type is always specific at very low level (cpu level). The compiler decides for us when we don't say and we don't say when it is not important any compiler decision is ok.

Of course this is not realistic and the reason is simple. The way we do daily business leads to imprecise implementation. I say horse, and it can be implemented either as a white horse or black horse or anything in between (hopefully a common one at least). It is tolerated in our daily life because the implementation is often cheap and can be directly verified at every level. E.g. I say get me a horse, I verify your facial to see if you heard, and verify you action to see if you are about to act, and I get in between gossips to get warnings of any surprises, ..., all the way until I actually have the horse. And along any of these steps, if I find I actually meant a white horse and you are not getting a white horse, I interrupt your implementation and make corrections. In programming, writing code is expensive (programmers are paid well, takes long time), and the typical only feedback is when the code completes and the user uses the software (at which point the user is getting the feedback, not programmer), and when things go wrong, user have no idea how to make correction, and this is even true for programmers, who have no idea what is inside their libraries and the nuances of the programming languages they are using.

TL;DR We are stuck.

To solve this scenario, I think the first step is to make every one be able to program, then the implementation can become cheap, and the feedbacks can become short and quick, and the compiler can become less rigorous, and then we may be able to program like we speak -- program the way we thinks.