const in dmd v2.011

Steven Schveighoffer schveiguy at yahoo.com
Wed Feb 20 19:39:03 PST 2008


"Derek Parnell" wrote
> On Wed, 20 Feb 2008 19:03:56 -0500, Jason House wrote:
>
>> It seems like you may have read some very early D 2.x docs on const and 
>> not
>> read the later D 2.x docs.  The const design has changed a lot.
>
> Thanks Jason. I know that keeping up with the changes in const theory and
> practice is a full time job in itself ;-) but I had been aware of these
> later tweaks.
>
>> Derek Parnell wrote:
>>> Observations:
>>> ** It appears that there is no practical difference between 'const(C) c'
>>> and 'const C c'.
>>
>> This is the definition of transitive const.
>
> Yes it is. What I was bring to attention is the potentially confusing
> syntax options that are now available.

To address this point, let me show you why.

5 + 2
is equivalent to
(5 + 2)

The parentheses add nothing, but are not illegal.  Similarly

const(C)
is equivalent to
const C

The parentheses add nothing.  However,

5 + 2 * 3
is not equivalent to
(5 + 2) * 3

Because now the parentheses are telling the compiler which operation comes 
first.  Similarly:

const C *
is not equivalent to
const(C) *

The parentheses are defining the scope of the const statement.

>
>>> ** It appears that 'const(char[])' and 'const const(char)[]' are
>>> equivalent and also not implemented well (or the error messages are just
>>> bad).

I think some of the issues you point out, especially where you have 2 
seemingly similar statements where one statement gives an error and the 
other does not, are real bugs that should be filed.

However, you need to realize that in order to support generic 
const-ification, this kind of syntax needs to be supported.

For example, if you have a type T, and you want a const version, you can do:
const T t;

However, what if T is an alias for const(C)?  Now, const T is equivalent to 
const const(C), and that reduces to const(C), which is necessary to allow 
for the type system to work.  If const const(C) was different than const(C), 
then the type assignment would be all screwed up.

Similarly, if you don't allow const const(C) because the const is redundant, 
then you can't const-ify any type by doing const T because then generic 
programming gets really ugly, with lots of static ifs.  I think the way it 
works is the way it should.

>>
>> const(char)[] means the char's within the array can't be changed, but the
>> array itself can change (ie. length changes, concatenation)
>
> Yes, I know what it means. Again what I'm bring attention to is the
> confusing nature of this syntax.
>
>   const(char)   X; // 'X' is const.
>   const(char)[] X; // 'X' is not const.

Again, this is the scoping of the parentheses limit the scope of const to 
the array elements.  If you have the generic type:

struct S(T)
{
   T[] x;
}

Now, if you do

S!(const(char)) c;
S!(char) m;

S is defining a mutable array of T's, clearly from the declaration.  Even in 
c, you can mutate the x array without affecting any data that x points to, 
thus not violating const rules.  To prohibit this would be 
counter-productive, and cause lots of headaches.  The goal of the const 
system should be not only to ensure const data doesn't change, but should 
also be to ensure non-const data CAN be changed.

>
> also this ...
>
>   const(char)* k; // 'k' is a mutable pointer to immutable data.
>   const(char*) l; // 'l' is an immutable pointer to immutable data.
>

Same thing.  The parentheses limit the scope of const.

> The forms 'const(char)[]' and 'const(char)*' ignore transitivity while
> other forms enforce it. It could be confusing, no?

This is not so, they do not ignore transitivity.  Transitivity means that if 
you have a pointer to const data, anything that data points to must also be 
const.  If the array was const but the data pointed to could be changed 
through the array pointer, then transitivity would be broken.

-Steve 




More information about the Digitalmars-d-learn mailing list