> That raises an obvious question: when should we expect the Go 2 specification that breaks old Go 1 programs?
> The answer is never. Go 2, in the sense of breaking with the past and no longer compiling old programs, is never going to happen. Go 2 in the sense of being the major revision of Go 1 we started toward in 2017 has already happened.
Why is backwards compatibility such a religious sin for Go? Python made it through a backwards-incompatible source change. I understand breaking backwards compatibility would be difficult on a short timescale, but on a long-term time scale people would migrate. Source rewriters would handle most of the transition. Over 3-5 years I could see a source-breaking change play out positively for some of these newer languages like Go and Rust. And arguably, they sorely need it.
Go developer experience:
* install the newest compiler
* clone the code
* go build
Python developer experience:
- clone the code
- setup virtual env (otherwise you will break your system)
- install very specific version of interpreter because lib x supports only Python from 2020, because Python breaks compatibility in minor versions
- no, you can't just update lib x withut updating python and other deps
- install deps (hopefully author of the code pinned everyting, otherwise you're fucked)
- never update any deps or you will suffer
As somebody who writes a lot of python, I'm going to quibble, but your statement isn't unfair. :)
My quibble would be "don't use lib x". 99% of the time, you don't need an unsupported 3rd party library from 2020. In the worst case, you can copy the subset of lib x that you actually need, the copied code will typically just work, verbatim, in a later python version. In summary, the "common" path travelled by footgun-aware python programmers is not this bad.
But yeah, it'd be nice if the language constraints meant you couldn't end up in a situation like this, and it'd be nice if we didn't have to learn-by-footgun as much in the python community.
TBF, Python is just an old language that comes with early-mover advantages and disadvantages. Like an old house, we have just learned to live with (i.e. avoid) certain floorboards.
> I understand breaking backwards compatibility would be difficult on a short timescale, but on a long-term time scale people would migrate.
It's funny to see people expressing this view because the "2 to 3 migration problems" is still a lively conversation in the Python world. I happen to agree with you and view it as a price of success - but at the same time I think it's obvious that you will pay an outsized price in community sentiment for even reasonable timescales for EOL'ing old versions.
"Why is backwards compatibility such a religious sin for Go?"
I think the best way to understand it is that it is a first-class feature of the language. Thus, for Go specifically, it is like asking "Why is it a statically-typed language?" or "Why is the language compiled rather than interpreted?"; these are not bad questions but to a large degree the answer is that was a major choice made at the start of the language. And "why won't they get rid of it?" is in the same class of questions as "Why won't Python just become a statically-typed language?", which, is, again not intrinsically a bad question, but one that is certainly in a different category from "why won't Python adopt this particular bit of syntax sugar in their next version?"
That the designers of Go would consider that a "feature" and so many programmers probably find classifying "backwards compatibility" as a feature a completely befuddling concept ("that's not what a feature is!") is probably a pretty good microcosm of the difference between the gestalt of programmers as a whole and the Go designers.
Has python really though? still my company has a bunch of 2.7 lying around that not one is touching.
I would like to flip your question on its head and ask why does any language need a breaking change ever? Might as well create a new language in that case
While I can't say for sure, one or the reasons I seem to recall from the Python 3 transition was that the Python 2 design was pretty much a dead end. There where so many limitation and wrong design choices that it would keep the language from moving forward. That does seem a little aggressive, but it does feel like Python picked up a lot of steam once Python 3 was viable (something that happened way earlier than many care to admit).
Our code base wasn't huge at the time, a few 100.000 lines of code. Getting everything running was a week of work for three people. Sure many had way more complicated code, and some depended on some idiosyncrasies of Python 2 making thing more complex, but a lot of people acted like the Python developers shoot their dog. Mostly these people either simply didn't want to do the work or their particular niche was made ever so slightly more complex... or they depended on unmaintained libraries which is bad in it's own way. Python 3 was always going to be able to do everything Python 2 could, yet a large groups of people acted as if that wasn't the case.
Still not the best transition ever devised, we had to wait until 3.2 to get the speed to a point where it's wasn't an issue for all but the largest users.
The Python 3 upgrade process for many projects was incredibly painful. "Mercurial’s journey to and reflections on Python 3" should be required reading for anybody with rose-tinted glasses of the migration.
There was, of course, a Hacker News thread discussing the article, and a fair few people decided to blame the Mercurial developers for handling the migration inelegantly. Because that's how you win over an audience of developers - reassuring them that if Python has a backwards-compatibility break, Python fans will go out of your way to try and blame you for writing bad code. And not, perhaps, the fact that Python was missing things like a u string prefix and % bytestring formatting until 3.3 (2012) and 3.5 (2015!!!) respectively.
If I sound peeved, I really loved Python in the 2.x days, and the way the 3.x transition was handled broke my heart and prevented me from using the language for pretty much an entire decade. There are lessons to be learned from the transition, but not if we ignore the real problems that the transition caused. More importantly, we need to recognize that Python is not the Python we know today because of how "well" the transition was handled, but because Numpy and Matplotlib swooped in and gave Python new niches to excel in at just the right time.
All well and good when u have an active dev team who knows the code. Have fun walking into a code base that has just been running for the last 5 years and all the consultants that created it have left.
> why does any language need a breaking change ever
that's easy - because it's impossible to design everything right right away, and for many things also impossible to make it right later without breaking compatibility, while those improvements are valuable
New language for each breaking change also doesn't make sense when there is a lot of continuity
Python programmers just self-selected themselves into a set of programmers who care about backwards-compatibility less than other programmers. You can see this attitude all over the Python ecosystem. And even in standard Python it’s not just one backwards-incompatible change, but a series still made from time to time. Programmers from C++, Java and Go worlds wouldn’t accept it as easily.
> Python made it through a backwards-incompatible source change.
It took them a decade and permanently tarnished their perception with many programmers. They "made it through" in a similar way to how cancer survivors enter remission.
It's probably because Google has no interest in rewriting the hundreds of thousands of lines of Go code they have internally and don't want to expend the resources to maintain a v1 and a v2.
> Python made it through a backwards-incompatible source change.
That's skipping a few fact, isn't it? Let's call it what it was. Python was a victim in a cataclysmic software disaster of biblical proportions. It spend 10 years in rehab afterwards but miraculously made it through yes.
> Python made it through a backwards-incompatible source change.
It made it, but it was a rough few years, and the string model changes while mostly welcome (though not perfect) were a pain, we still find bugs from time to time.
Things also got a lot better once the community figured how to do proper multiversion sources even though it was more limiting.
A statically typed langage would have it a lot easier, by virtue of both the API and the semantics changes being much more flagrant, as well as the compiler making it easier to actually mix different versions of the langage across different packages (or even source files).
this always seemed like a nightmare to me. even so today years after python2 was officially sunset, documentation is still all over the web that may never catch up.
yes technically the language got over it but i would hold this up as an example of a reason not to break backwards compatibility. having to manage multiple interpreter versions when i'm just trying to run software on my computer, what a pain in the neck.
Backwards compatibility matters to the Go developers because all of them worked with the same codebases for 20+ years. I remember rob pike showed me a source file that had been written before I was born (1973) but is still part of (I think) Plan9.
Especially for a compiled language, I would think it is significantly easier to make automated code porting which is guaranteed to be correct. Or at least enough to handle the 99% of a code base which is likely not impacted.
Swift shipped source-breaking updates earlier in its lifetime. I honestly don't really know of a story where a source-incompatible update killed a language. People grumble, then they move on.
The pain of breaking changes is proportional to the volume of code affected by the breakage. This usually means breakages early in the lifetime are easy because there's relatively little code. For mainstream languages that have a decade or more of widespread usage, a breakage is a big deal.
> I honestly don't really know of a story where a source-incompatible update killed a language.
Perl. I mean, Perl isn't strictly dead, but its share of the market plummeted. Python almost certainly would have suffered a similar fate if it weren't for the explosion of interest in scientific/numeric computing (which more than made up for massive attrition to other languages, including Go).
> I honestly don't really know of a story where a source-incompatible update killed a language.
Death may not come as swiftly (heh) as you think. I know a few people (including myself) who, when deciding which language to add to their toolbox, had decided against Swift because of its reputation as “that language that always breaks code”, among other reasons. There are just a few anecdotal data points, of course, but I don't think it's controversial to say that a history of messy updates definitely makes new people less likely to learn a language without an absolute necessity.
Killed, in the sense of no one ever migrated? Certainly not. Killed, in the sense of hugely impacting the eco system and the community? Quite regularly.
Python seems to finally mostly have made the transition, but there is just a lot of software around which will never be ported to Python 3. Perl almost completely went away, until finally development of Perl 5 gained some traction, but also with promises of maintaining compatibility.
Print statements were a mistake. If you forbid breaking changes, you have no way to fix past mistakes in the language design. There’s noting inherently "right" in refusing to do breaking changes.
Do you mean byte strings vs. strings in Python 3 or did you actually like string handling in Python 2, because that basically "Tell me that you only allow ASCII without telling me that you only all ASCII". I can see the issue with byte strings in Python3, it's annoying that you have to think about both strings and byte strings, but for dealing with actual text having everything just be unicode was reason enough to upgrade from 2 to 3. We deleted so much code dedicated to dealing with encoding during our switch to Python 3, everything just became better.
I had an IRC markov-like bot in Python. It used to be so simple in Python 2:
- the bytes come in from the IRC server
- they go in a string in the log, I can print this log to the console even if it has some IRC control codes (there will be a garbage character here or there but that's OK)
- if I want to make a bold/color/etc I can just throw \xwhatever in the string. if a word from the log had bold in it and it's repeated back it will also have the bold in it.
Then I reluctantly ported it to Python 3 and it was awful. Python now had to micromanage every single string to ensure I don't have any "naughty" bytes in it. Conversions to/from byte/string everywhere. Massive headache every time I wanted to read or write IRC encoded strings to a txt file or print them to the console or anything.
In Python 2 the encoding only lived outside the program, in my terminal, text editor, and IRC clients. Bytes went in, bytes went out, and everyone was happy. Python 3 decided it needed to know exactly what was going on every step of the way and didn't trust me anymore, forcing me to do an elaborate song and dance to get anything done.
I prefer my tools to have as little an opinion as possible. Let me open the door while I'm driving, let me run my web browser as root, and let me print \xDE\xAD\xBE\xEF to the console.
> Python now had to micromanage every single string to ensure I don't have any "naughty" bytes in it.
Oh that is annoying, our use case just fitted better into how Python 3 works. We went the opposite way. We micromanaged strings all over the place to ensure that encodings would always be correct. We needed unicode but also connected to Windows systems, which uses their own weird codepage system. Encoding and decoding was everywhere along with encoding detection. Python 3 made all that go away.
> The answer is never. Go 2, in the sense of breaking with the past and no longer compiling old programs, is never going to happen. Go 2 in the sense of being the major revision of Go 1 we started toward in 2017 has already happened.
Why is backwards compatibility such a religious sin for Go? Python made it through a backwards-incompatible source change. I understand breaking backwards compatibility would be difficult on a short timescale, but on a long-term time scale people would migrate. Source rewriters would handle most of the transition. Over 3-5 years I could see a source-breaking change play out positively for some of these newer languages like Go and Rust. And arguably, they sorely need it.