If the ordering of the keys is not in the spec, a programmer should not assume the ordering of the keys. If none of the training material says or implies that the keys will always be ordered, why would a programmer?
The new and improved algorithm happens to preserve ordering. Future algorithms might not. The dictionary data structure does not specify order preservation so that, in the future, a better algorithm that doesn't have this same side effect could be used.
> a programmer should not assume the ordering of the keys
The Python community has many inexperienced programmers, even non-technical people. Particularly, it's so beginner friendly by making it very, very easy to get started with the REPL, etc. A lot of these programmers aren't even going to look at the docs and even if they do, might not understand them.
Programmers should not try to access memory beyond the end of an array. They should not attempt to add ints and strings. They should not give a function a float when it expects a struct.
But they do. So we try to design languages in such a way as to minimise the likelihood of these mistakes going unnoticed.
Designing a language to minimize the likelihood of these mistakes is a motivation for language design, but usually far from the primary.
"Programmers should not try to access memory beyond the end of an array"
^ Right, and when they do, it's called a logical bug, something to be fixed. A programmer relying on the incidental but unspecified behavior of a function would be making a similar mistake.
But, we learned from C that the possibility of trying to access arbitrary parts of memory means that programs will end up trying to access parts they shouldn't. So, higher level languages like Python solve the problem by having memory-safe types like lists, which preclude the possibility of making this mistake.
Similarly, if we randomise the ordering of keys in the dict then it's impossible for a programmer to make the mistake (consciously or unconsciously) of relying on ordering.
At the cost of an additional processing step to scramble the keys. The balance between safeguarding ignorant or overactive programmers against the performance of a critical builtin type is not going to tip in that direction.
The whole reason we can even have this discussion is because a new algorithm was developed to give us the increased performance in the first place.
why would a programmer? Because the programmer would just run the code and check what different methods return as result. Then if it looks like the ordered keys, said programmer will rely on this behavior.
For instance, I'm writing some javascript recently. I try a little array in the console, if Array.keys() returns the orders keys, I will assume it is, and would check the docs (where?) only if I had a problem. Something unstable should not look stable. I agree with the Golang way, make it look like what it is by the specs.
I have trouble understanding a programmer who takes a couple samples of a method's behavior and feels confident enough to trust that as the actual behavior of the function. At least guard you're flippant assumption with a check or something!
The problem is not to add some checks (asserts? No, just kidding), the problem is that you're quickly writing a little thing for a demo out an experiment, and faster than you'd expect these ten lines of innocuous code have grown in a gigantic ball of mud upon which many businesses are built.
To me the less worse way to handle this is a softened TDD, where a consequent part of the code is covered (described, checked, structured) by a suite of reasonably atomic automated tests.
"try a little array in the console, if Array.keys() returns the orders keys, I will assume it is"
That may work for some toy script you write for your own use, but must be avoided if you intend to engineer a program.
Certainly, that kind of thinking will lead to very bad results if you ever do low-level multi-threaded programming or try to write portable code.
For multi-threaded programming, "is this call thread-safe?" is not something answered in a test, and certainly not in a quick test.
For portable programming, you simply cannot run the test on all possible systems.
In general, when you program like that, you will not only rely on implementation details that may change (for example, this may change for arrays with lots of entries) but also forget to handle error conditions.
It is very easy to inadvertently add dependencies on key order. For example, if you are generating HTML, you might have something like:
print("<a " + " ".join(k+"=\""+v+"\"" for (k,v) in d.items()) + "/>")
And d would be a dict of attributes for the anchor element. The code will produce different output depending on computer which is not what you want because it can cause subtle problems for other systems expecting a certain output.
Several compiler bugs have been of this kind so it is not only newbie programmers that make these mistakes.
It shouldn't affect the way a browser renders the HTML. But there are many possible scenarios in which the order is relevant for some other reason.
Suppose you have another system monitoring the web page generated by the above code. Like a cdn or something. That system would think the web page is constantly updated as the code of the HTML page would be different each time it accessed it, leading to lots of redundant work if it has to update caches, check outbound links and so on.
How many programmers have you worked with? (People will assume all sorts of things that are not true if it makes their job slightly easier, or even harder)
The new and improved algorithm happens to preserve ordering. Future algorithms might not. The dictionary data structure does not specify order preservation so that, in the future, a better algorithm that doesn't have this same side effect could be used.