string types: const(char)[] and cstring

Walter Bright newshound1 at digitalmars.com
Sun May 27 01:09:40 PDT 2007


Derek Parnell wrote:
> You said "strings should be immutable" and I saying that seems odd because
> my experience is that most strings are meant to be changed. 

I'm going to argue that your experience is unusual. I do a lot of string 
manipulation (after all, that's what a compiler does) and the strings, 
once constructed, are essentially always immutable. In conversations 
with many others, my experience is commonplace.

But still, in D, nothing prevents you from using mutable strings.

> So now I'm thinking that we are talking about different things when we use
> the word "string". I'm guessing you are really referring to compile-time
> generated string data (e.g. literals) rather than run-time generated string
> data.

I'm referring to the arrays of characters, generated or literals.


>>> So 'const(char)[] x' means that I can change x.ptr and x.length but I
>>> cannot change anything that x.ptr points to, right?
>> Right.
>>
>>> And  'invariant(char)[] x' means that I cannot change x.ptr or x.length and
>>> I cannot change anything that x.ptr points to, right?
>> Wrong. The difference between const and invariant is that invariant is 
>> truly, absolutely, immutable. 
> 
> Huh??? Isn't that what I just said?

No. You said for const you could change x.ptr and x.length, but for 
invariant you could not. For both const and invariant, you can change 
x.ptr and x.length.


> Now I'm even more confused about these
> terms. They are just not intuitive, are they?

The problem is I have failed to explain them. Invariant data can go into 
read-only memory. Const data can be changed by another reference to the 
same data (just like in C++). In other words, const is a read-only 
*view* of the data, whereas invariant data is read-only for all views of it.


>> Const is only immutable through the 
>> reference - another reference to the same data can change it.
> 
> Ok ... so this below won't fail ...
> 
>   void func(const char[] parm)
>   {
>       char [] q;
>       q = parm;
error, q is not const.
>       q[0] = 'a';
>   }
> 
> or is the "q = parm" not really permitted.

Right.

> 
>>> So what syntax is to be used so that x.ptr and x.length cannot be changed
>>> but the characters referred to by 'x' can be changed?
>> final char[] x;
> 
> 
> Given the syntax on the form "  void func(<X> char[] parm) ", is the table
> below true ...
> 
> *-------------------------------------*
> | <X>         + parm.ptr  |  parm[0]  |    
> |-------------+-----------------------+
> | const       | mutable   | immutable |
> | final       | immutable | mutable   |
> | invariant   | immutable | immutable |
> |             | mutable   | mutable   |
> *-------------------------------------*

You've got invariant wrong, it's mutable|immutable.


> I'm sorry I'm a bit slow on this ... but what is the difference between
> "invariant" and "const final" ? Is it that "invariant" is sort of a global
> effect but "const final" is only in effect for the specific reference it
> occurs on.

First differences: final is a *storage class*. const and invariant are 
*type constructors*.

final only refers to the actual value that a symbol has, and it means 
that, once a value is assigned to a symbol, that value can never change. 
If the value is a pointer or reference, what it points to *can* be changed.

int x = 3;
final int* p = &x;
p = null; // error, p is final
*p = 1; // ok

const(int)* q = null;
q = &x;  // ok, q is not const, and now *q is 1
*q = 2;  // error, *q is const
*p = 5;  // ok, but now *q is 5, too!
x = 6;   // ok, but now *q is 6

invariant(int)* s = null;
s = &x;  // error, cannot implicitly convert int* to invariant(int)*
int y = 4;
s = cast(invariant(int)*)&y; // ok, trust programmer that y is immutable
*s = 3;  // error, *s is immutable
y = 5;   // undefined behavior, as y is never supposed to change,
          // and compiler assumes *s is still 4

Note that int* can be implicitly converted to const(int)*, and 
invariant(int)* can be implicitly converted to const(int)*.

> I'm not looking forward to reading the docs on this. I hope you get a lot
> of people to edit the docs to make it understandable for everyone.

The thing is actually rather simple, but I am having trouble finding the 
right words to express it. Certainly, the mishmash of C++ const has 
badly muddied the waters about what const means.



More information about the Digitalmars-d-announce mailing list