On Fri, 13 Aug 2010 15:46:30 -0400, Tomek Sowiński <j...@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

Reply via email to