Best practices of using const

Yatheendra 3df4 at gmail.ru
Fri Jun 21 06:07:59 UTC 2019


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, 
levels
    // of members (and a subset of the overall methods) in a 
5-deep type hierarchy are const
with:
    "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 
> wrote:
>> On Wed, Feb 13, 2019 at 11:32:46AM +0000, envoid via 
>> Digitalmars-d-learn wrote:
>> 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.
>>
>>
>> T

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 
const.

On Monday, 18 February 2019 at 06:50:32 UTC, Marco de Wild wrote:
>
> I agree that const by nature unfortunately kills lazy 
> initialization.

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.
> ...

+1.

Or I haven't understood why ranges would ever ever need to be 
const.
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 
functionality?



More information about the Digitalmars-d-learn mailing list