AFAIUI you can mix Rust 2015, 2018, and 2021 crates; so a developer can update their own crate to 2021, while not having to completely re-write the dependencies which are still Rust 2015. With Python 2 -> 3, my understanding was that everything had to be updated recursively.
That said...
> I personally like the “edition” concept of Rust a lot better: get over with all necessary breaking changes in one swoop, but then have a new (hopefully long) era of backwards compatibility.
What they describe actually sounds somewhat similar:
> At some point in the future, the PSC may decide that the set of features, taken together, represent a big enough step forward to justify a new baseline for Perl. If that happens, then the version will be bumped to 7.0. If this happens, Perl 7 will still be backwards compatible with Perl 5 by default – you'll have to put use v7; at the top of your code to use all the new features. Think of use v7 like Modern::Perl and similar modules.
So the 'use <feature>' is going to be similar to Rust's "nightly unstable features", but actually being stable; and 'use vN' is going to be like Rust's Editions.
It's just that they don't think they've accumulated enough features to release a new Edition yet.
First, significant new language features are introduced all the time, even in stable, all of them enabled by default (indeed, there’s no way to turn them off).
Nightly’s #![feature(…)] is strictly for experimental stuff that is buggy and/or will change until stable release. I’m sure you know this, but all of those are intended to be backwards compatible! I think that’s a big difference.
Incompatible changes in Rust never happen with “features” (as you know, stable doesn’t even have those), but only with “editions”. The goal of an edition is to carve out a large chunk of future design space, like introducing some keywords for planned features, or rarely, fixing really annoying inconsistencies that require a breaking change. They feel a lot more proactive (we want to do this, we need an edition) than retroactive.
Rust editions are not versions of the language, they're just syntax.
New features of the language in a new library or compiler version work fine in all editions unless they require syntax which isn't in your chosen edition.
Rust 2015 edition is only restricted to the syntax from 2015, all the features of today are available unless they're gated off somehow by syntax. For example the "async" keyword didn't exist in Rust 2015, so, you won't be using that from 2015 edition even today. But even though in 2015 you certainly couldn't go around evaluating u32::checked_div() in a constant, it works just fine in Rust 2015 edition today, because it's not gated by syntax.
Perl 'features' are lexically scoped, and could be applied in a finer-grained style, if you like. Shutting something off locally is done pretty commonly (e.g. to silence an ignorable warning).
The Perl devs have a deprecation cycle to remove mis-features, even if that breaks backwards compatibility. They don't, as far as I know, make much effort to line that up with major version changes[1], it's more a matter of making sure there's a long period of warning.
[1] The difficulty of course, was that for a long time the language now known as Raku was squatting on the next major version, "6", hence the need to jump to "7" to avoid confusion with Raku.
Anyway, on practice they didn't work like that.
You can mix "Python 2" and "Python 3" code, but the problem is (was) that the semantics in Python 3 surrounding string handling changed so much that in reality this was tricky to accomplish, and Python's dynamic untyped nature didn't help either.
But it was definitely possible to write libraries that worked with Python 2 and 3; I've made a few. It was pretty tricky though, and often led to bugs.
Python 3.0 was released in 2008, the fact that 14 years later 2.7 is still widely available (and often the default python, e.g. in my openSUSE Tumbleweed system here) means that the "buzz" was more than warranted.
Also of course things would migrate, it isn't like there was any choice on that matter (and projects like Tauthon that tried to provide a choice had several "Pythonistas" attacking it).
There was another choice. This is what I mean: however bad you think py2->py3 was, people are using py3 now unless they've got really good reasons not to and are prepared to suffer. When it came to perl5/6, it turns out over time most people choose "neither".
SUSE didn't update the link like others did so it's not really that py2 is the default, but python2 was always named python. It's going away anyway: https://www.suse.com/releasenotes/x86_64/SUSE-SLES/15-SP3/in...
This new trend is about a decade old by now. Pandas was released in 2011, numpy in 1995. Google released Tensorflow to the public in 2015.
it wasn't inevitable, but it was damn likely.
As someone who is still supporting multiple desktop GUI applications in python, what did they pick instead? I'd love move off Python, but nothing else seemed to have the proper maturity.
Only if you count "not making a choice" (ie. staying with Python 2) as a choice. But this isn't really practical since everything else is pushed towards Python 3.
Well, the hang-up in the roll out of "Perl 6" (now, Raku) gave people ammunition to shout about how "Perl is dead", but the central trouble was a lot of people wanted to spread that word. Myself, I think the success of a weirdo outsider language was making some insiders very upset, and they were fighting back any way they could.
Supporting older, variant behavior isn't really causing problems for the devs, from what I hear, when it does they go after it with the deprecation cycle.
It does not, though? You have to update the entire file (really crate) at once, but that’s really not much of a challenge as it’s near exclusively syntactic, and syntactic changes are easy to make, just fix compiler errors.
I feel like you didn’t go through the Python migration yourself and just go off of the echoes you got from it, but the issues in the Python migration were not “updating code is hard”. It was really the easiest part, and could mostly be done mechanically (which incidentally `cargo fix` provides for when migrating between editions).
The challenges of the Python migration was:
- You had to wait for all your dependencies to be updated before you could migrate yourself, commonly this was mixed with API updates while at it especially at the start, this is not an issue in Rust because there is no dependency between crate editions, I can use edition 2018 and depend simultanously on edition 2015 and edition 2021 crates.
- Many changes were semantic in nature, there was no way to check them statically, instead they were runtime changes (in types or behaviour), which made ensuring they were correct a lot more challenging; editions do not cover or allow for this.
The Python migration wilfully included fixes to long-standing semantics issues of the language (though whether all were improvements, or whether they went far enough remains a matter of debate), and this as well as the incompatibility are what made it an issue.
If it had been entirely syntactic and a per-package or per-file thing it would have been much less of an issue (not an entirely non-issue as things like library contents are a runtime concern in python, but still…). And that’s what rust editions are.
What this gives you is high confidence that when inserting a few lines somewhere, that fancy new for loop simply works. No need to scroll to the top if the file and remember which exact release of the 27 in the last year introduced the feature.
With perl you can upgrade your language version whenever you like, and do it reasonably safely, because there's a lot of emphasis on backwards compatibility.
Perl may actually have a "always gimme the latest features" option, but I don't know what it is, because things like that aren't really that popular in the perl world-- we want old code to keep working the way it always has.
Now, your new argument depends on how hard it is to migrate a single file. If that’s sufficiently easy, you simply do it. Migrating to the last Rust edition, I had to fix maybe a handful of things in an entire crate; most files didn’t have to be touched at all.
My argument isn't really about migration is about not having to migrate if you don't need the features while not losing anything - by opting in to the new features/changes you can use whatever you want without wasting time on changing your code to do the same stuff just in a different way (unless you decide that this different way is actually better and worth doing, but that'd be your choice and not something indirectly forced on you by the ecosystem you decided at an earlier point in time to rely on).
A 2018 edition project (declared in the project config) is pinned to that version forever. You would have to switch to a new edition explicitly.
Well that was easy.
Perl already had python2->python 3000 fiasco before python: PERL6
Perl had the could be bytes, could be characters fiasco in 5.8, but they didn't include a bunch of other difficult changes at the same time. 5.8 could be a bit rough around unicode, but 5.10 was pretty solid as I recall, and you can always use bytes; in a scope where you need bytes.
But to use that new feature they'd need to modify their code anyway, so this isn't really an issue in practice, is it?
> I personally like the “edition” concept of Rust a lot better: get over with all necessary breaking changes in one swoop, but then have a new (hopefully long) era of backwards compatibility.
How is this any different from having a repeat of the python2->python3 fiasco (which, AFAIK, Perl developers are trying to avoid)? Making piecemeal (if needed) changes is much easier than having to update a ton of code and that is even more important when that code wasn't touched for a long time.
EDIT (i put it here since i already got three replies on the same thing): i understand that you can mix two different files with different "editions" but it still makes it hard to update these files themselves.