www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Top 4 use cases for mutable references to const data

I posted some of this in the other thread, but I think it deserves a thread of
its own. The problem is this: under the new const regime, it sounds like it
will be impossible to declare tail-const class references without
head-constness too. Walter's argument against this is that he can't think of a
use case when one would want a non-const reference to const data. I, on the
other hand, really think that's the whole _point_ of constness. I usually write
methods short enough to never need head-const (sadly, my colleagues don't
always agree), so rarely use the concept at all. The idea of a reference to
constant data, though, is what make const useful to me in the first place,
since one can pass a const reference to another component and know that
component isn't messing with it.

So, here's my top 4 (actually the first 4 of many, many, many that came to my
mind, but 4 that are much more difficult to do without mutable references) of
having mutable references to const data. Without this, const is simply unusable
for me, and I'm sure others will agree. Basically any case where one would want
a mutable reference is a use-case for possible constness, since to be able to
mutate that reference under the new regime, you would needed to cast away the
constness (thus removing its usefulness). This gets especially hairy in the
case of invariant.

Example 1: Member variables:
----------------------------------------
The following would be ILLEGAL without mutable references to const data:

class Foo { }
class Bar
{
    const(Foo) foo;
    this(const(Foo) foo)
    {
        this.foo = foo;
    }
}

This would be somewhat possible with structs (using struct literals, struct
initializers, etc.)

Example 2: Iteration through a linked list of classes
----------------------------------------------------------------------
The following would be ILLEGAL without mutable references to const data:

class Node
{
    Node next;
    int data;
}

const(Node) search(const(Node) first, int value)
{
    const(Node) current = first;
    do
    {
        if(current is null)
            return null;
        if(current.data == value)
            return current;
        current = current.next;
    }
}

If you ask why a linked list of classes and not structs (to which mutable
pointers to const data would be possible), remember that linked lists aren't
always a general list of elements, thy could be a filter chain or a
user-subclassable list of timer events as used in SEDA, or anything else tow
which polymorphism applies. If you want to say "composition is a better design
descision here than polymorphism," I hear ya, but we shouldn't be forced to
change entiore design patterns to support constness, and taht this applies to
basically all sorts of iteration (possibly even returning a class reference
with an opApply).

Example 3: Caches
--------------------------
This is too complex an example to simmer down to a 5-10 line example, but
imagine a caching function (class, struct). You wouldn't want your cache
function changing the data you pass in, so you want to mark that data const.
However, the cache only keeps a limited set of references to the data (perhaps
the most frequently accessed, or most recently accessed, or everything until
memory starts getting low, where it starts discarding). To keep this cache,
you'd need mutable references (after all, the data that's currently cached is
changing), but the cache never changes the data, so these references should be
tail-const. Again, impossible.

Example 4: Associative Arrays:
-----------------------------------------
The following would be ILLEGAL without mutable references to const data:

class Person { }
const(Person)[string] people;

//...

const(Person) awesomePerson = "Robert" in people;
if(null is awesomePerson)
{
    awesomePerson = new Person();
    people["Robert"] = awesomePerson;
}
// Do stuff with awesomePerson

---------------------------------------

I could go on for a while, but most of the other cases I can think of are more
coding style things that could be worked around with temporary variables, etc.
And, of course, all this stuff can be worked around with casting. However, that
defeats the purpose of constness entirely, IMO.

PS My spell checker's suggestions for "constness": moistness's, moistness,
moistnesses, colorfastness, robustness
Sep 11 2007