Why do we have transitive const, again?

Jonathan M Davis jmdavisProg at gmx.com
Thu Sep 22 01:12:13 PDT 2011


On Wednesday, September 21, 2011 10:15:31 Mehrdad wrote:
> I can't find the thread, but I remember someone (bearophile?) mentioned
> that the reason we have transitive const is to support purity.
> 
> I don't think I understand why this is necessary, though -- could
> someone please explain why we have transitive const, and what problems
> it fixes?

I believe that it comes down primarily to three things:

1. To provide strong compiler guarantees (unlike C++)
2. immutability
3. simplicity

Take this C++ code for example

class C
{
public:
    ....

    vector<int*> getter() const
    {
        return _var;
    }

private:

    vector<int*> _var;
}

int func(const C& c)
{
    ...
    vector<int*> v = c.getter();
    *v[2] = 3;
    ...
}

c is const, and yet func changes its state. That makes it very difficult (if not 
impossible) for the compiler to give any guarantees about const beyond 
complaining when you directly try and alter a const variable. So, the compiler 
can't use const for optimizations or whatnot unless it's dealing with a 
primitive type - even if there was no mutable and you couldn't cast away const 
and alter variables.

Now, what if you add immutable into the mix? The compiler _must_ be able to 
make guarantees about immutable. If the above were D code (with non-
transivitive const/immutable) with immutable, then the compiler couldn't 
actually do anything useful with immutable, because it couldn't guarantee that 
c was actually immutable. In order to do stuff like pass objects across threads 
with send and receive, you must have compiler guarantees that the object is 
actually immutable. And because anything which is const could actually be 
immutable (aside from value types where there is no difference between const 
and immutable), const must provide all of the guarantees that immutable does. 
And so, they must both be transitive.

Now, on some level at least, we could avoid the need for fully transitive 
const using some sort of tail and head const where we fully specified what was 
and wasn't const or immutable. Stuff would still have to be fully immutable to 
be passed along with functions like send and receive, and you'd lose some 
optimizations when using head or tail const instead of fully transitive const, 
but it could be done, and there are situations where it would be useful. 
However, doing that gets far too complicated. It would make const too hard to 
use. It was explored early in D2 and dropped precisely because of the 
usability issues. Instead, we went with fully transitive const which could be 
minimally restricted with parens.

- Jonathan M Davis


More information about the Digitalmars-d mailing list