D const design rationale

Sean Kelly sean at f4.ca
Sat Jun 23 08:43:43 PDT 2007


Daniel Keep wrote:
> 
> Sean Kelly wrote:
>> Daniel Keep wrote:
>>> final int x;        typeof(x) == int;
>>> const int y;        typeof(y) == const int;
>>> final const int z;    typeof(z) == final const int;
>> Hm.  Just to clarify, we both agree that the value of a final integer
>> (ie. case 1 above) is effectively constant, correct?
> 
> Indeed.
> 
>>> "Wait; why is final part of the last type, but not the first?"  And what
>>> does this mean if you want a class member with final-style binding, but
>>> (final const) type semantics?
>>>
>>> final (final const(int*)) foo;
>>>
>>> As opposed to
>>>
>>> final invariant(int*) foo;
>> Perhaps I'm missing something, but I would rewrite this as:
>>
>> final const int* foo;
>>
>> Thus foo cannot be reassigned once set and the data foo refers to may
>> not be changed through foo.  This is a slightly weaker guarantee than:
>>
>> final invariant int* foo;
>>
>> Which says that the data foo refers to is immutable, but I am skeptical
>> that this guarantee actually matters much to users.
>>
>> Or am I completely misunderstanding?  And why the parenthesis in the
>> second declaration?
> 
> (When I wrote the below, I missed precisely what you were saying: the
> problem with writing it at "final const int*" is that you've got both
> final and const as a storage class; I assumed you were using them as a
> type constructor.)
> 
> Ok, let's try this instead: in the current system, we have
> 
> class Foo
> {
>     final invariant(FunkyType) funky;
> 
>     this(bool superFunky)
>     {
>         if( superFunky )
>             funky = cast(invariant) new FunkyType;
>         else
>             funky = some_global_invariant_funky;
>     }
> }
> 
> In this case, we have a final storage (so we can assign the value during
> the ctor), and an invariant(FunkyType) value type.
> 
> Under your proposal, invariant is replaced with (final const); if we
> want the above, it'd become:
> 
>     final final const(FunkyType) funky;

Under my proposal, this would be:

     final const FunkyType funky;

> But how does the compiler tell that second final is storage class or
> part of the type constructor?  Remember, we could be dealing with a
> template that's just shoving "final" out the front of things, so we
> can't assume two finals ==> one is a type constructor.  So we'd probably
> have to do this:
> 
>     final (final const(FunkyType)) funky;

Hm.  I'm afraid I don't understand all this talk about type constructor 
vs. storage class.  What I get from the above is that:

     final const FunkyType funky;

represents a fixed reference to an instance of FunkyType, which cannot 
be changed through the reference.

> We can't use *just* "final const FunkyType funky" because then we'd have
> an "invariant" storage class: which means the initialiser would have to
> be a compile-time constant.

Why would it have to be an "invariant" storage class?  It seems I'm 
missing something fundamental here.

 > Incidentally, the above is also probably
> equivalent to:
> 
>     final(final const(FunkyType)) funky;
> 
> Which really doesn't make any sense anyway...

>>> I think the thing here is that you're shifting the complexity from
>>> invariant into final; instead of invariant meaning two different things
>>> with two very different appearances, you've got final meaning two
>>> slightly different things with almost identical looks.
>> I only see final meaning one thing: that the associated value may not be
>> reassigned.  For concrete types like integers this is effectively the
>> same as const, but as Walter said, the integer would be addressable when
>> final but not when const.  Perhaps this is the source of confusion?
>>
> 
> Yes, but it *also* means "can assign to in a ctor".

Right.  That's compatible with what I said.  It can be assigned in a 
ctor but not *reassigned* once assigned.  Just like 'const' in D 1.0.

> Like Lars said, I do think that if there's a way to simplify or
> consolidate this, then we should take it.  That said, I can see a use
> for each of the various cases the new system allows for, and I don't
> want to see any of them cut off in the name of "well *I'm* not going to
> use it, and I don't like that keyword, so it has to go!"[1]. :)

I agree.


Sean



More information about the Digitalmars-d mailing list