The Status of Const

Steven Schveighoffer schveiguy at yahoo.com
Fri Aug 13 13:10:15 PDT 2010


On Fri, 13 Aug 2010 15:46:30 -0400, Tomek Sowiński <just at ask.me> wrote:

> Graham St Jack napisał:
>
>> The major language hassle for me is that a class reference has the same
>> const/immutable/shared type as the object is refers to, unlike pointers.
>> I know that Rebindable is a workaround, but I don't find it satisfactory
>> - essentially it uses brute-force casting to defeat the type system, and
>> isn't syntactically identical to the bound type.
>>
>> [snip]
>>
>> Is there any plan to introduce some way of having a mutable reference to
>> an immutable class object on the heap? Do others see this as a problem
>> at all?
>
> I see it as a huge problem too. Crazy idea: introduce @tail to be used  
> in combo with const/immutable. I'd find it even useful on structs.
>
> @tail immutable struct Ref {
>     int[] array;
>     int* pointer;
>     int value;
> }
>
> This would be the same as:
>
> struct Ref {
>     immutable(int)[] array;
>     immutable(int)* pointer;
>     int value;
> }
>
> No need to examine types field by field to impose such a popular  
> constraint on your structure. But the real money comes from finally
> having a language-legal way to express a mutable reference to an  
> immutable class.
>
> Not to mention that backwards-compatibility is kept (no book will  
> suffer).

This exposes another important deficiency for const/immutable.  One of the  
coolest things about arrays is how you can implicitly cast them.  For  
example, I can implicitly cast int[] to const(int)[], or const(int[]) to  
const(int)[], or immutable(int[]) to const(int)[].

But we have no equivalent way to do this for custom types.  Why care?   
Well, one of the most useful data concepts ever needs this ability --  
ranges.

It's one of the major reasons dcollections has not yet added const  
support.  If a dcollections container wanted to support const properly, it  
means I need to define a const range, a const cusror, an immutable range  
and an immutable cursor.  Why?  Because a const(range) is utterly useless  
-- popFront doesn't work (it modifies the range!).  In addition, it would  
be nice to be able to specify that a function accepts a const range, and  
pass it a non-const range for an implicit conversion.  But if I define two  
ranges, the compiler sees them as unrelated separate types, so it will not  
allow it.

Your way to specify a tail const would be really helpful to achieve this  
goal, because it's not templated, so you avoid some awkward decisions.

One thing however, do you have a problem making @tail a type modifier  
instead of a storage class?  Because I need that in order to do the  
implicit casting.  i.e.:

struct Ref {
    int[] array;
    int* pointer;
    int value;
}

@tail immutable Ref x;

is equivalent to declaring x as a struct like this:

struct Ref {
    immutable(int)[] array;
    immutable(int)* pointer;
    int value;
}

I'm assuming you meant this, because I don't know how you would declare a  
tail-const class reference if it was simply a storage class.

I also liked Michel Fortin's const(Object) ref idea, but it really only  
addresses the tail-const class reference problem.  Having a universal  
method to apply tail const that is valid for all types really makes things  
easier.

Note to all who discussed this before: when we last discussed how to do  
tail-const, @attributes were not available, this would be a good time to  
revisit how we could use attributes as Tomek suggests.

-Steve


More information about the Digitalmars-d mailing list