const - Best practices

Peter Alexander peter.alexander.au at gmail.com
Sun Jan 2 22:06:47 PST 2011


On 2/01/11 10:43 PM, Jonathan M Davis wrote:
> http://d.puremagic.com/issues/show_bug.cgi?id=1824
>
> For the const/immutable situation to be totally useable, several dmd bugs must
> be fixed. Some of the major ones are 1824 (Object is not const-correct), 3659
> (opEquals() and const needs to be sorted out), 4867 (postblit doesn't work with
> const objects), and 3748 (inout is broken). The auto ref issue which came up
> recently when discussing the fact that const ref doesn't work with temporories
> needs to be resolved as well.
>
> There are a number of critical issues with const and immutable as things stand.
> The result is that that they can quickly become rather problematic to use
> correctly, if not outright impossible. There are definitely cases where const and
> immutable can and should be used, but you really have to want to use them at
> this point to be able to manage it, because they have a lot of problems. And
> until those problems are fixed, there's no way that we can know what the "best
> practices" of const in D will really be. To really understand that, we need to
> write code which uses const and immutable heavily and really see how it all
> works out. We can speculate on what we think will work well and point out areas
> where it's clear that there will be problems or which will pretty much need to
> use const in some manner (like opEquals()), but not enough people have been
> using const for there to be much experience with it, and those who have tried
> have consistently run into serious bugs which prevented them from using it like
> they'd like to.
>
> Another big thing is that Phobos as a whole is not const-correct. I don't
> believe that much attempt has been made to ensure that many of Phobos' functions
> work properly when const and immutable are used. The lack of tail-const for
> arbitrary ranges is one of the big open issues which has yet to be resolved. As
> I understdand it, there are some things work for arrays which will never work
> for other ranges. And some things have worked in the past because of compiler
> bugs. Such bugs have hidden issues (including issues relating to const) and made
> it look like const worked where it doesn't. Until Phobos is properly const-
> correct, there are a lot of cases where you're not going to be able to use const
> (this is also true for purity, though I believe that the situation is quite a
> bit worse for purity).
>
> I expect that there is going to have to be a definite focus on fixing bugs related
> to const and immutable in both the compiler and in Phobos before const and
> immutable will really be generally useable. It's on the TODO list, though it's
> not clear whether that or dynamic libraries is next after the 64-bit port
> (regardless, the 64-bit port is taking longer than expected so, it's going to be
> longer before the rest of the stuff in line gets focused on and fixed).
>
> Personally, I think that const should be used as much as it can be reasonably
> used. But it does generally preclude any kind of caching of values and the like
> that you could do with logical const (though you could do things like have a
> mutable version of a getter on top of a non-mutable one and have _it_ cache the
> value, so that if either it or the const version is called later and the value
> doesn't need to be recalculated, the const one can use the cached value and
> still gain some efficiency from caching). So, if you're expecting to have to cache
> values and the like, then don't use const.
>
> But honestly, in my experience in C++, I have almost never used mutable. And
> when I have, it's generally been for mutexes and the like (which won't be
> necessary in the same way in D). Doing things like caching calculations is
> extremely rare. So, the lack of logical const really wouldn't affect much from
> what I've seen. The transivity of const is what really affects things IMHO
> (things like returning a list of mutable objects from a const getter where that
> list is a member variable of the object aren't going to work in D, but they work
> just fine in C++ since the container itself isn't copied). I'm sure that there is
> code out there which does high-cost calculations on a regular basis and pretty
> much needs to be able to cache the results to be properly efficient, but that is
> not the norm. So, while some people are going to acutely feel the lack of
> logical const, a _lot_ of people are going to be able to use const in D very
> much like they do in C++ without having any issues with the lack of logical
> const. _Transivity_ may very well make it impossible to use const like they
> would have in C++, but the lack of logical const really isn't that big a deal in
> _most_ cases.
>
> - Jonathan M Davis

Huge thanks Jonathan for writing that. Cheers.

So basically, const-correctness in DMD is completely broken :-(

I had no idea the situation was so dire, which in itself is a major 
problem. I don't envy people outside this NG that have no idea what's 
going on at all.

I found this in one of those bugs. It's a post from Andrei, and I think 
it basically sums up my thoughts on const.

--- begin quote

I'm thinking of our current stance on const: if you don't care about const,
don't use it and for the most part it won't intrude on you. For example,
string's use of immutability is fairly confined.

opEquals is a stark deviation from the stance above. It *will* intrude. The
classic example is this:

class Widget {
     bool opEquals(Widget);
}

Compiling this issues:

Warning: object.Object.opEquals(Object o) is hidden by Widget

It only gets downhill from there:

struct Widget {
     bool opEquals(Widget) { return true; }
}

This time it's an error:

Error: function test.Widget.opEquals type signature should be const bool(ref
const(Widget)) not bool(ref Widget)

So you simply can't "not care" about const. But then it's all getting viral
because cons is viral. Consider the user grudgingly agrees to add const, and
then...

class Widget {
     private Gadget g;
     bool opEquals(const Widget rhs) {
         return compatibleGadgets(g, rhs.g);
     }
}

But now it's still not fine because compatibleGadgets is also written 
without
caring about const. It's all a mess.

Now consider that the user capitulates and decides to use const wherever
applicable. Things will still not work in certain cases. For example if
opEquals must compare members that are lazily computed, you can't make it
compile. Cheating by casting away const will mess up a variety of 
assumptions.

As an aside, I know what it takes to define lazily computed state to 
work with
const, but Walter is at the bottom of a 5000 TeV potential hole that spells
like "this is like C++ mutable and C++ mutable is incorrect, therefore I 
will
not process any information henceforth". So I am unable to even start
explaining that to him. Besides, assuming Walter is convinced of the
correctness of the feature, it's unclear whether it will pull its weight. It
will complicate the language, and the benefits, while there, are rather 
subtle.

So I don't know what to do.

--- end quote

:-(



More information about the Digitalmars-d mailing list