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