any news on const/invariant?

Janice Caron caron800 at googlemail.com
Thu Nov 29 07:00:13 PST 2007


Yes, Oskar is right in his analysis of const vs invariant
declarations. And now that I think about it, it occurs to me that
NOTHING IS EVER CREATED CONST. Everything that is created in D, is
either created mutable, or is created invariant. All literals are
invariant. Everything created using new is mutable. .dup and .idup
generate mutable and invariant respectively, but there is no .cdup.

And this makes perfect sense. After all, if const means "a readonly
view of something", then there must be a "something" for it to be a
readonly view /of/.

Thus, as Oskar pointed out, a statement like

    const x = 3;

is actually pointless. Either you want x to be mutable, or you want x
to be constant. In the former case, "auto x = 3" would do the trick;
in the latter case, "invariant x = 3" should work. But "const x = 3"
is redundant, because nothing can modify x /anyway/. Casting away
const is undefined, so we can't do that, and since we can't do that,
nothing can change it - ergo, it is invariant. Thus, we should really
be writing

    invariant x = 3;

For this reason, it seems to me that "const as a storage class" makes
absolutely no sense whatsoever. Const things are not stored, /ever/.
Invariant things are stored (they occupy bytes of ROM or RAM
somewhere); mutable things are stored (they occupy bytes of RAM
somewhere), but there is really no such animal as a const "thing" -
there is only "pointer to const", or "array of const", or "custom
collection of const" ... and all of those things are examples of
const-as-a-type-constructor, not const-as-a-storage-class.

Ah, but what about functions?, I here you ask. Well, in the case of
class member functions, it's the other way round: we need const, but
not invariant. Further back up this thread, Bruce Adams pointed out
that it makes very little sense to define a class member function as
being invariant. I did respond to that pointing out that it had a
/literal/ meaning in the context of the D language, but in reality,
it's a nonsensical fiction. To create an invariant class instance,
you'd have to do:

    A a = cast(invariant(A))(new A);

and unless you do that, then you can never call an invariant member
function. What this means is that Bruce is basically right - defining
a member function to be invariant is as pointless as defining a const
literal. It seems to me that in both cases /one keyword will suffice/.
So why not let "const" do double-duty?

That is, we keep
(*) const as a storage-class
(*) const as a type-constructor
(*) invariant as a type-constructor

and we lose
(*) invariant as a storage class

with the caveat that when const-as-storage-class is applied to types
which require storage, it actually means invariant (but when applied
to member functions it retains its existing meaning). If we were to
adopt this practice then:

     const x = 3;
     auto p = &x;

would result in x having type invariant(int), and p having type
invariant(int)*. Since invariant can implicitly cast to const, this is
guaranteed not to break anything.

It would also mean that

    invariant x = 3;

would become a compile error, since invariant would no longer be an
attribute. This seems to me to be a slightly more preferable idea than
Oskar's one of redefining "protected", since, under my scheme, "const"
would be the keyword you'd use in practice, most of the time. You'd
use it when declaring variables, when declaring member functions
const, and when promising not to modify stuff. Only rarely would you
need to type the more lengthy "invariant", but it would still be there
(as a type-modifier only), should you need it.



More information about the Digitalmars-d mailing list