Watching the ~11 years of Python 2 to 3 adoption has been somewhat painful, and many libraries have had to offer support for both across much of that time. (And I believe at time of writing Google isn't even 100% ported to 3 yet - please correct this if I'm wrong).
I couldn't be happier that Python 3 is finally king though, and major projects like Django are able to go entirely to 3 now.
Breaking changes in languages can be important and good, but they really can affect adoption of the new version by existing users, which is tough as often major users hold some sway in the ecosystem.
JavaScript has the no breaking changes problem even worse, because you have to support (within reason) all major interpreters existing in the wild, and cannot easily change the code, so "transpiling" has become the normal.
Microsofts support lifetime for IE11 also means this isn't changing soon. Lots of old browsers in the wild (even though it has improved dramatically over last few years).
Backwards compatibility for a language means that old source code still works without having to update it, even if you can do so automatically.
Also worth pointing out that C++ has broken backwards compatibility in a very small number of cases, e.g. the `auto` keyword has changed meaning. Nobody ever used it before so it wasn't a problem in practice.
this portrayal of the python 2 to 3 migration does not represent the majority of the community! and yet we keep hearing it over and over because "large" codebases were not migrated on time.
this migration was a software engineering problem. i hope by now, people have learned to write dumb code and avoid clever tricks whenever they can. performance and clever tricks get tied to languages, OSes, & hardware versions. python is no exception!
not saying don't do them. just saying know what you are getting into.
again, the issue is not entirely due to breaking changes. but python made it too easy. c++ for example would have given people such a hard time that they wouldn't have even bothered. python's was too permissive.
i have seen the python 2.7 codebase that shipped with the original appengine. it always felt like traveling to a different world whenever the debugger gets into their code...
This led to all manner of playing fast and loose with str as byte[] usage. I've seen inline asm and even machine code in python.
Now it's the new millenium and oh look, ascii-char won't cut it as your language implementation of strings.
There's also a lot of new syntax though, which does have high costs in cases like generators, and shipping the regenerator runtime because you need your code to run everywhere.
To my knowledge they have extended syntax and added modes, but not actually made any breaking changes.
A mode was a way to avoid making breaking changes.
What I missed from my comment is not just about the engines in use, but also that all old spec confirming JavaScript should still run, in all new environments.
That is backwards compatibility.
But there's so much poorly written JS on the web that there is a chance!
Modern browsers will say 12, old browsers (IE 8 and down) will say 10.
They also changed to (at least more) deterministic ordering of object keys and I wonder how much code worked
They also changed to a (more) deterministic ordering of object keys and I wonder how much software behaved differently / broke as a consequence...
My "favourite" JS quirk is some of the IE versions where it would break if you called console.log without the console open, as it was undefined.
So many quirks, I think I may have slightly overstated the compatibility element.
They've just been careful to try to minimize the impact.
- automatically done
- isolated within a module
As long as these are true, the issues caused by breaking compatability are minimal.
It's really the Python model where it's all-or-nothing and you de-facto need to remain compatible with two releases as everyone transitions that's the problem.
This only exists in fairy land. In practice, mixing code from different versions is always the root of subtle bugs and ABI/API mess. For me in front of a big chunk of legacy code, I'd rather wrap them in a separate process and communicate with the remaining part through RPCs if possible.
That's why people have a love/hate relationship with it. The language is full of BS but the path of least resistance is to learn the ins and outs of the BS rather than to do a full rewrite of your huge codebase in a sane language. Learning the ins and outs of C++ is a one time hit, after that you can use it quite happily. So new projects get started in C++ and the cycle repeats.