Am I mistaken in saying that we are conflating:
"anything that is logically const should be declared const"
// makes perfect sense
// e.g. the lowest 2, and some branches of the 3rd and 4th,
// of members (and a subset of the overall methods) in a
5-deep type hierarchy are const
"most code/data should be declared const"
// no! isn't efficient code all about mutation?
// no grounds for, e.g.: "ideally, no more than 40% of code
should be doing mutation"
On Wednesday, 13 February 2019 at 16:40:18 UTC, H. S. Teoh
On Wed, Feb 13, 2019 at 11:32:46AM +0000, envoid via
Unfortunately, that guarantee also excludes a lot of otherwise
useful idioms, like objects that cache data -- a const object
cannot cache data because that means it's being mutated, or
lazily-initialized objects -- because once the ctor has run,
the object can no longer be mutated. Most notably, D's
powerful range idiom is pretty much unusable with const
because iteration over a range requires mutating the range
(though having const *elements* in a range is fine). This
doesn't seem as bad at first glance, but it wreaks havoc on
generic code, another thing that D is purportedly good at.
It's very hard (and often impossible) to write generic code
that works with both const and mutable objects.
So ironically, the iron-clad semantics of D's const system
turns out to be also its own downfall.
The point about generic code (reiterated by many) is intriguing
on its own; until now, I hadn't explicitly thought about const
even for my C++ template library code (whatever little I have of
those). Any pointers to other posts or articles elaborating this
a little bit?
I believe the other points probably matter when interacting with
every other feature (I would have to write some of my "real" code
in D to see if I hit it on my own), but there doesn't seem to be
anything unusable about them on their own.
The inability to have a const caching object seems correct. The
way around would be to have a wrapper that caches (meh). If that
is not possible, then maybe caching objects just aren't meant to
be const by their nature? Isn't memoize a standard library
feature? I should look at it, but I wouldn't expect it to be
On Monday, 18 February 2019 at 06:50:32 UTC, Marco de Wild wrote:
I agree that const by nature unfortunately kills lazy
Lazy initialization - is this the same as post-blit? At the cost
of copying (justifiable? maybe), doesn't D have a way to
copy-construct a const/immutable struct object from a mutable
one? If there is a way (or will be - there is a recent posting
and a Dconf talk about copy constructors), does the copying
negate the benefits of lazy initialization?
However, I don't really understand why const is a problem with
ranges. Const elements are not a problem. Iterating over a
range consumes it (if I understand correctly). It does not make
sense to be able to consume a const object, so from my point of
view it's perfectly logical to disallow iterating const ranges.
If I'm missing something, please correct me.
Or I haven't understood why ranges would ever ever need to be
After all, in C++, what use is:
std::vector::const_iterator const iter = sequence.begin();
About the only kind of use would be:
std::vector::const_iterator iter = sequence.begin();
std::vector::const_iterator const iterEnd = sequence.end();
What are ranges if not an encapsulation of the above