DIP 1018--The Copy Constructor--Formal Review

Manu turkeyman at gmail.com
Mon Feb 25 02:08:20 UTC 2019


On Sun, Feb 24, 2019 at 4:40 PM Walter Bright via
Digitalmars-d-announce <digitalmars-d-announce at puremagic.com> wrote:
>
> The problem with C++ const is it only goes one level, i.e. what I call
> "head-const". If you pass a T to a const parameter, anything T references
> remains mutable. It's more of a suggestion than anything reliable or
> enforceable. It only works if your data structures are simple aggregates, not
> graphs.
>
> D's const has teeth. Nothing can be modified through T. If you're used to
> writing code that tweaks const data under the hood, D's const will never work
> for you. Yes, it means rethinking how the data and code is organized, and that
> can be painful. But it is how FP works. FP offers a number of advantages, and
> D's const offers a path into that.
>
> For example, most of DMD is written in the C++ style where functions frequently
> are written to both return some information *and* tweak the data structure. This
> does not work with const. It needs to be reorganized so that getting information
> about a data structure is separated from modifying the data structure. I've made
> such changes in a few places in DMD, and have been very pleased with the results
> - the code is much easier to understand.
>
> To sum up, you're quite right that you cannot write C++ style code using D
> const. It hast to be in a much more FP style. If you're not accustomed with FP
> style, this can be a difficult learning process. I know this from firsthand
> experience :-)

I agree with these facts, but your case-study is narrow, and you have
to stop saying "C++ style", which it really isn't.
It's very much D-style... almost all D code is written this way.
It's in conflict with too many other patterns, and they're not "C++
patterns", they're very legitimate D patterns.

Function pointers and delegates are often incompatible with const;
practically any code with some sort of call-back behaviour, and
anything that forms *any form* of traversible network where you'd like
any part of it to const fails. I've never written a program that was a
perfect tree. A small feature library maybe, but not a program that
does anything interesting.

It's great that we can write FP-ish code in D, it's particularly
useful for narrow, self-contained tasks; it helps me intellectually
factor some potentially complex leaf-level call-trees out of the
program structure, and I appreciate when libraries take that form; it
helps them have a smaller footprint in the larger complex suite. But
const doesn't play into that much, and if that can't interact with
normal D code, which is most code, then it's just not a useful piece
of language.

The proposition that everyone start writing straight-up FP code in D
is unrealistic, and if they wanted that, they'd use Rust every time.
People are here because they don't want to write Rust.

> For me the only real annoyance with const is I often cannot use "single
> assignment" style declarations with pointers:
>
> I.e.:
>
>      const int* p = &x;
>      p = &y; // error, good
>      *p = 4; // also error, not what I wished
>
> This C++ const does provide, and it's good, but it's not really worth that much.

Are you serious? You can't honestly say C++ const is worthless?
Especially in comparison to D's const, which is _actually_ almost
completely worthless.
It really doesn't make anything better, and there's a whole class of
troublesome language issues that emerge from it being defined this
way.
The way C++ defines const is such that const can be used, and you can
integrate that code with other code.

I mean it seriously where I say I've tried to defend D's const for as
long as I've used D, but I can't escape the plain and honest reality
that D's const is not useful for almost anything practical.
Even the way you describe it above is like indulging in a little bit
of fetish, and I understand that, I try that every time thinking "I'm
gonna get it right... this time for sure! What a cool guy I am!", but
that never works out beyond a very small scope. const with a narrow
scope is where it's least impactful.

Then to make matters worse, `const` is a combinatorial testing
nightmare; you write your code mostly without const (because
conventional wisdom), and then you try and call into your lib from
various contexts and it just doesn't work. You need to set-up heaps of
tests to try and prove out that your code is const-robust that are
very easy to miss otherwise.
Then someone else tries to use your code with their code which is
using const (attempting at least); I've seen lots of libraries where
it would have been possible to support const, at least to some extent,
but they just didn't because "don't use const", but the result is that
the client of that library can't use const in their own code because
the lib undermines their effort in some way.

I don't like this concept that a piece of library code 'supports'
const, but that's where we are.

None of this is issue with C++ const, because it's defined in a way
that's useful, but also sufficiently localised that it doesn't invade
users code outwards.

const undermines its own value far too often, and with the effect I
describe above where one author's dismissing of const cascaded
outwards, it seals its own fate.
D's const rarely helps anything, it's honestly just a shiny thing that
you waste time chasing, and then you lose, and then the community
reminds you not to use const. It's incompatible with D in a lot of
fundamental ways, and if you argue that everyone should stop writing D
code and start writing something a lot more like Rust code instead,
you gotta admit that's a self-defeating argument?

If you're honest with yourself, we recognise that after 15-20 years of
the sorts of recommendations you make above not taking effect in
real-world D code, you must admit it's an objective failure. I haven't
wanted to admit it for as long as I've defended it... but I think it's
indefensible.

Also, the scope of your experiment above is not based in practical reality.
You said something to this effect "I reworked a little bit of code in
DMD, and was happy with the result. It feels simpler". I can write a
little bit of const-correct code too, but you need to get back to us
when you've covered all of DMD. This is a compiler; almost a perfect
tree, one of the most structurally simple and uniform programs
imaginable. But people don't write compilers, they write gigantic
metropolis's of libraries and glue, by 10s or 100's of authors
collaborating against a ticking clock.
If there were reasonable patterns to make D const work, we would have
discovered them by now, and there would be articles on the matter.
Apparently they don't exist though, and as such, it's usefulness is
constraints to narrow call-trees, very close to the leaf of your
application, and remains incompatible with a lot of other core
language and patterns.

On Sun, Feb 24, 2019 at 4:40 PM Walter Bright via
Digitalmars-d-announce <digitalmars-d-announce at puremagic.com> wrote:
>
> The problem with C++ const is it only goes one level, i.e. what I call
> "head-const". If you pass a T to a const parameter, anything T references
> remains mutable. It's more of a suggestion than anything reliable or
> enforceable. It only works if your data structures are simple aggregates, not
> graphs.
>
> D's const has teeth. Nothing can be modified through T. If you're used to
> writing code that tweaks const data under the hood, D's const will never work
> for you. Yes, it means rethinking how the data and code is organized, and that
> can be painful. But it is how FP works. FP offers a number of advantages, and
> D's const offers a path into that.
>
> For example, most of DMD is written in the C++ style where functions frequently
> are written to both return some information *and* tweak the data structure. This
> does not work with const. It needs to be reorganized so that getting information
> about a data structure is separated from modifying the data structure. I've made
> such changes in a few places in DMD, and have been very pleased with the results
> - the code is much easier to understand.
>
> To sum up, you're quite right that you cannot write C++ style code using D
> const. It hast to be in a much more FP style. If you're not accustomed with FP
> style, this can be a difficult learning process. I know this from firsthand
> experience :-)
>
> For me the only real annoyance with const is I often cannot use "single
> assignment" style declarations with pointers:
>
> I.e.:
>
>      const int* p = &x;
>      p = &y; // error, good
>      *p = 4; // also error, not what I wished
>
> This C++ const does provide, and it's good, but it's not really worth that much.


More information about the Digitalmars-d-announce mailing list