The Status of Const

Tomek Sowiński just at ask.me
Fri Aug 13 14:10:20 PDT 2010


Steven Schveighoffer napisał:

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

Glad you like it. Time ago I had an overzealous attempt to port QuantLib to D and I quickly found out that the *only* sort of const I 
needed was tail const. It's what I ended up declaring fields of my structs because if just one field is from-head const, the restrictions are 
basically the same as if the whole struct was const (which is correct but...). It's what the parameters of pure functions should implicitly 
be declared to (no big deal, but still). From-head const gives me no upper hand in the multi-threaded domain, just pain in my rectum 
domain. Sure, from-head const is at times useful, but tail const is the workhorse.

> 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.

Yes.

> 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.

Yes.

> 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.

Yes. ;)


Tomek


More information about the Digitalmars-d mailing list