On Tuesday, 30 July 2019 at 05:30:30 UTC, Jonathan M Davis wrote:
In principle, it's good to use const when you know that data
isn't going to change, but that gets far more complicated when
you're dealing with generic code or even with classes, since as
soon as you use const, everything used with that template then
needs to work with const, or in the case of classes, every
derived class has to use const for their override of that
function. Sometimes, that's fine, but that's usually when
you're either requiring that const always work, or you're in
control all of the code involved, so you know that you're not
going to have to deal with issues like caching. It's issues
like this that led us to decide a while ago that putting
functions on Object was a mistake, since it locked all classes
into a particular set of attributes (and even if we changed
which attributes those were, it would still cause problems).
The ProtoObject DIP (which would add a base class for Object
that didn't have anything on it) will hopefully fix that, but
that still hasn't been finalized yet.
In the case of ranges, on top of the general issues with const
and generic code, their API just isn't designed with const in
mind. Fundamentally, you need to be able to mutate a range to
iterate through it. It would be different if we'd gone with
more of a functional-style, head/tail solution where you have a
function like head to get the first element, and a function
like tail to return a range with the first element popped off,
but for better or worse, that's not the direction we went.
However, even if we had, issues like caching or delayed
calculation would still come into play, and if you require that
const work on something like empty, that prevents certain
classes of solutions. Of course, on the flip side, without
const, you don't know for sure that unwanted mutation isn't
happening, but what would really be needed would be some kind
of "logical" const rather than the full-on const we currently
have, and that would be very difficult to implement. C++'s
const _sort_ of allows that, because it has so many loopholes,
but on the flip side, you lose most of the guarantees, and it
mostly just becomes documentation of intent rather than
actually enforcing logical constness. In practice, I find that
D's const tends to not be terribly useful in generic code, but
it's far more of a problem with libraries that are publicly
available than with code where you control everything and can
change stuff when you need to. This article I wrote goes into
further detail about the issues with const in general:
http://jmdavisprog.com/articles/why-const-sucks.html
The situation with ranges would be improved if we had some kind
of const or inout inference for templated code like we do with
other attributes, but I don't know quite how that would work or
what the downsides would be.
- Jonathan M Davis
That was a great article you wrote. Const has been one of the
more difficult concepts for me to grasp when I moved from python
to C++ and then to D. I also never understood immutable and the
difference with const. Your article makes that really clear.
Thanks for sharing.
Matt