Thoughts on Backward Compatibility
H. S. Teoh
hsteoh at qfbox.info
Fri Feb 16 04:38:03 UTC 2024
On Fri, Feb 16, 2024 at 01:44:51AM +0000, Paul Backus via Digitalmars-d wrote:
[...]
> ### What can we learn from this for D?
>
> First, that the success and popularity of a programming language is
> mostly determined by factors other than stability and backward
> compatibility (or lack thereof).
+100. Over the past 5-10 years or so, I've been finding myself wishing
that D would introduce some breaking changes so that it could clean up
some of its dark, ugly corners that have been like flies in the ointment
for a long time.
At the same time, I'd had deprecations and breaking changes that are
really rather minor, but extremely frustrating, because:
> Second, that even without an edition bump, small-scale breaking
> changes with easy migration paths aren't a big deal.
The worst feeling is when you upgrade your compiler, and suddenly you
find yourself having to do major code surgery in order to make
previously-fine code work again. Having an easy migration path for
breaking changes is very important.
I'd also add that the migration path should be *easy*: it shouldn't take
too much thought to upgrade the code, and should not involve tricky
decisions based on subtle semantic differences that require deep
understanding of the code to make the right choice.
The std.math.approxEqual deprecation is a major example that I keep
running into. It's intended to be replaced by isClose, with all the
right intentions. But it was frustrating because (1) it didn't feel
necessary -- previous code worked fine even if there were some
pathological cases that weren't being handled correctly. (2) The
deprecation message didn't give a clear migration path -- isClose has
different parameters with subtly different semantics from approxEqual,
and it wasn't obvious how you should replace calls to approxEqual with
equivalent calls to isClose. There were also no easy defaults that you
could use that replicated the previous behaviour; you had to sit down
and think about each call, then look up the docs to be sure. (3) The
choice of name felt like a serious blunder, even if it was made for all
the right reasons.
All of these added up to a very frustrating experience, even if the
intentions were right.
If we could have done this over again, I'd have proposed to keep the old
semantics of approxEqual, perhaps add another parameter that would use
the new semantics. And make sure the deprecation message is clear about
how exactly you go about deciding what to put in the new parameter.
I.e., for lazy authors not changing anything would let their code
continue to work as before; if they wanted to have the new semantics
they'd have to explicitly opt in.
> Third, that even with an edition bump, large-scale breaking changes
> that make migration difficult should probably be avoided.
Yes, large breaking changes are a no-no. Unless my old code can
continue compiling as before, and I have to opt-in to the new stuff.
Editions would help with this, but it still depends on the execution.
There should always be a good migration path that doesn't require you to
rewrite 5-10 year old code that you no longer remember the details of
and can no longer confidently reimplement without spending
disproportionate amounts of time to re-learn the ins and outs of it.
> Fourth, that breaking changes should be used to give D programmers
> more of what they already like about D, not to take the D language in
> new directions.
TBH, @nogc, dip1000, @live, etc., feel a lot like D trying to go in
entirely new directions. The fact that it's been years and still
practically nobody understands exactly how it works and what it does, is
not a good sign. And all this while things like `share` and static
initialization of AA's are stagnating. Built-in AA's are one of my
major reasons for choosing D, and seeing it languish for years with
elementary features like static initialization not fixed is quite
disheartening. Worse when it feels like D wants to move to newer
pastures when its current features are still half-done and has
problematic corner cases. I.e., what I like about D is stagnating,
while new features that I have little interest in are being pushed on
me.
> To Walter, Atila, and the rest of D's leadership, I hope this post
> provides some helpful data points for you to take into account when
> designing D's language editions and planning future language changes.
>
> To everyone else reading this, I'd like to leave you with one last
> question: what do **you** like about D? What strengths does D have, as
> a language, that you'd like to see become even stronger?
[...]
What I like about D:
- Meta-programming power.
- CTFE should be improved. By a lot. It was a big disappointment
that Stefan's newCTFE never materialized. IMO we should be
improving this story instead of trying to chase rainbows like ARC
with @live and dip1000 and what-not. We should make this so good
that I'll never need to use an external codegen utility again. And
it should not introduce crazy compile times. This is a primary D
strength, its story should be maximally optimized.
- The template story should be improved. There should be a way of
working with templates that cut down on needless bloat. Lots of
room for exploration here. We shouldn't be confined by C++
limitations here. This is one of D's primary strengths and where we
can pioneer even more. One area is improving IFTI to make it work
for even more common cases. Another is recognizing common patterns
like chains of ranges, and optimizing symbol generation so that you
don't end up with unreasonably huge symbols. Esp. when it's a
one-of-a-kind UFCS chain (it's unlikely you're ever going to have
exactly the same chain twice with exactly the same template
arguments -- no point encoding every argument in the symbol, just
an ID that gets incremented per instantiation is good enough).
- Compile-time introspection and DbI. This is another huge D
strength, and we should be working on streamlining it even more.
- Clean up __traits(), make std.traits more sensible.
- Fix things like scoping issues with static foreach. Introduce
local aliases so that static foreach doesn't need crazy hacks
with {{...}} and temporary templates just for injecting new
identifiers per iteration without running into multiple
declaration errors.
- Improve the syntax for retrieving members of some symbol.
Something prettier than __traits(getAllMembers,...). This is a
primary D strength, it should be dressed in better syntax than
this.
- Maybe first-class types to make the metaprogramming story even
more powerful.
- GC. Instead of bending over backwards trying to woo the @nogc crowd
who are mass migrating to Rust anyway, what about introducing write
barriers that would allow us existing D users to use a much more
competitive GC algorithm? Stop-the-world GC in 2024 shouldn't even be
a thing anymore. We aren't in 1998 anymore. D should embrace the GC,
not sacrifice it for the sake of wooing a crowd that isn't likely to
adopt D regardless. Instead of trying to get away from the GC, what
about making the GC experience better for existing D users?
- Built-in AA's. It's been at least a decade. Why is static
initialization support still sketchy?
- Built-in unittests. The default experience should be top-of-the-line.
We shouldn't need to import a dub package for something beyond the
current dumb built-in test runner. Named unittests, the ability to
select which tests to run, the ability to run all tests regardless of
failure and show stats afterwards -- these are all basic
functionalities that ought to work out-of-the-box.
- Automatic type & attribute inference. `auto` was revolutionary when I
first joined D (C++ got it only years later). We should improve type
and attribute inference to the max (e.g., in default parameters for
enums: there should be no need to repeat the enum name). Nobody like
spelling out attribute soup, just like nobody likes spelling out
explicit types when it's already obvious from context. The compiler
should automate this to the max. A little bit of breakage here IMO is
acceptable as long as it gets us to an even better place. Have
negated attributes be a thing as well. In fact, make attributes
first-class citizens so that we can use DbI / metaprogramming to
manipulate it. This is what we should be focusing our efforts on
instead of trying to woo an amorphous group of hypothetical potential
users somewhere out there who aren't particularly likely to adopt D to
begin with.
T
--
People tell me that I'm skeptical, but I don't believe them.
More information about the Digitalmars-d
mailing list