Hopefully Carbon will succeed to achieve this goal.
Hopefully Carbon will succeed to achieve this goal.
C++ is definitely in a tough spot on the evolutionary trail. But the idea that the only path ahead is through incompatible changes seems likely to produce the same harmful effects.
Instead C++ has added all sorts of slightly incompatible features every three years since 2011, and is expected to do so again, periodically one of these incompatible changes is especially troublesome for important people and, like a naughty toddler, the committee promises not to do that again.
Yet, despite these incompatible changes which might have accidentally larger consequences than expected, for fear of the consequences other changes which were known to be incompatible but seem "worth it" are rejected. The worst of both worlds.
There is no plan for binary libraries across epochs, how different implementations would interact with each other, how multiple crates requiring different versions would interact with each other if their public API crosses versions with different semantics,...
There's a recent Reddit discussion which had zero pushback against changes but instead people who were disappointed that 2024 Edition won't land all the things they'd hoped for such as the improved Range types†
Without the Edition system we know from C++ that when you say "Why can't we have X?" the defenders appear to tell you that all choices except the status quo are impossible. They will do this regardless of how difficult such a change would be, and so this immediately deflates all interest in incremental improvement. It's a self-fulfilling prophecy.
But with Editions there's a lot of things we definitely can do. Once you open the door to that, it really drives enthusiasm and that enthusiasm can power some of the difficult changes you wouldn't even have considered in the C++ process.
† In Rust syntax like 1..=4 is compiled into the core type core::ops::RangeInclusive<i32> so this is a very natural way to express what you meant, and yet it's not a goofy special case it's just a normal literal like "Word" [an &'static str] or '€' [a char] or 1.2345 [a floating point defaulting to f64] -- however, we now realise these range types made some poor choices and if you made them today you'd make them implement Copy and IntoIterator, whereas the existing types implement Iterator and so in many cases cannot implement Copy. Ergonomically a Copy type would be much nicer here. Can we fix that? Well, the idea is, we make the new types (they exist in nightly Rust in the new core::range namespace but aren't stabilized) and then once we're sure they're exactly what we want we make a new Edition which changes the syntax transformation so that that literal is a core::range::RangeInclusive<i32> instead.
Whenever I hear someone say - "Gee, the only path ahead is a breaking change, sorry charlie!", what I really hear is - "I gave up thinking up a solution on how to do it an evolutionary way and I am lazy and just want to declare a revolution!".
There is always a pathway ahead on the evolutionary path. That's the premise at least.
Though on the other hand, we can only the imagine of not doing those changes. I reckon it would be at least as bad as the 2->3 changes. At the very least I wouldn't want to go back to a world where bytes and strings were unified.
Take something like std::unique_ptr. The basic problem is that it is absolutely capable of being written such that std::unique_ptr<T> has the same ABI as T, but it doesn't (instead acting as a T*). It's pretty damn trivial to write the necessary thunking between the ABI versions, so it's also absolutely possible to have both old-ABI and new-ABI coexist (something that was a lot more difficult for the infamous Python 2->3 transition). And other than the internal changes needed to give it a new ABI, there's not really any user-visible API that would need to be migrated. But it still can't be done because std::unique_ptr is used on the interface between library A and B, and how is A supposed to know which version of the ABI B is expecting, when neither A nor B?
> The goal is a tool-assisted migration of idiomatic code, not a fully automated migration of all code.
This does not mean that they will intentionally avoid to make possible a fully automated migration.
Normally the migration tools should be designed to attempt to do a fully automated migration, but whenever there are corner cases for which the effort to handle them completely automatically would not be worthwhile, then human intervention shall be required.
In C++ in particular one of the most obvious ways to write unmaintainable C++ which such automation couldn't be expected to migrate is via abuse of the pre-processor.
C++ retains the entire C pre-processor, which is a weird not-quite-language-agnostic text macro language on top of C. We can abuse this to write a different programming language, with different rules, and then at compile time the pre-processor transforms it into C++ which compiles.
I'm confident a migration tool could not always usefully translate this, and I'd argue that's not a failing of the tool so much as an inevitable consequence of writing this unmaintainable code.
Yep. I'm not a particularly big fan of Google languages, but focusing on bridging legacy code is brilliant.
Would have been interesting if Oracle had done the same with Java shortly after acquiring it. Java is so hemmed in by legacy compatibility it basically can't make any significant language or VM changes without making harsh compromises. Of course, Oracle would likely have supported legacy Java indefinitely, and made a fortune supporting/licensing it.