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