March 16, 2007
> IMHO (b) should be 'readonly' and (c) should be 'const'.
[snip]

vote++


Keywords
--------

I also think keywords can be written attached to one another. Like if you were to really call it "super const" have it called superconst instead of super_const.

It is like the foreach_reverse that we have in D. Why not call it foreachreverse instead.

I mean we don't write

   for_each()
   {
   }

but we write

   foreach()
   {
   }

const! is ugly.





March 16, 2007
Derek Parnell wrote:
> Yes! "const!" is bad form. Really bad. Horrible in fact. Just make it a new
> keyword please, without using non-alpha characters. Such as "readonly",
> "immutable", "keepyourgrubbyhandsoff", ... anything but using "!".

You can use "super const". We should be really really careful about adding new keywords; D already has tons, and I have a feeling we don't want it to become Cobol or dBase.

If there are ways to stay away from new keywords, we'll do so. I do realize that no matter the syntax, there will be people who won't like it. But avoiding adding keywords liberally is an overriding desideratum.


Andrei
March 16, 2007
On Fri, 16 Mar 2007 00:16:48 +0300, Andrei Alexandrescu (See Website For Email) <SeeWebsiteForEmail@erdani.org> wrote:

> a) final - a simple storage class controlling the immutability of the bits allocated for the symbol per se;
>
> b) const - type qualifier meaning an immutable view of an otherwise modifiable data. const does not control the bits of the object, only the storage addressed indirectly by it (transitively);
>
> c) "superconst" - denoted as "const!" or "super const": type qualifier meaning that the data is genuinely unmodifiable.

Great!

What about the influence of this storage classes on class method's signatures? Is this will be in D:

class Data { ... }

class Container {
  // non-const access to data.
  Data data() { ... }
  // const access to data.
  const Data data() const { ... }
}

void useContainer( const Container c ) {
  auto d = c.data(); // the type of d is 'const Data'.
  ...
}

?

-- 
Regards,
Yauheni Akhotnikau
March 16, 2007
Derek Parnell wrote:
>>> int a;
>>> const! int* p = &a; // error! cannot convert int* to const! int*
>>> final int b = 42;
>>> const! int* p1 = &b; // yah, b is truly immutable
>>> const! int* p2 = new const! int; // yah
> 
> I'm not sure about that last one. Does this mean that p2 points to an int
> that cannot change and p2 itself can no longer be changed? And what is the
> value in the int that p2 points to?

Good point. There is a little exception here. People expect that when they write:

const char[] str = "Hi!";

they can't modify str nor its characters. So they expect str to be final as well. We then arrange that if const appears in a data definition, that data is automatically made final as well. So the above is equivalent to:

final const char[] str = "Hi!";

If you don't want str to be final, do this:

const(char[]) str = "Hi!";

> Can you do this sort of thing ...
> 
>  int x = 5;
>  const! int* p2 = new const! int(x);
> 
> meaning that p2 now points to a 'final' int whose value is 5, plus p2 can
> never be changed now either.

Yes, you can.

>> ... and return values: "const char[] immutableTextProp()" ?
> 
> Hmmmm... does "const char[] X" mean that X.ptr can change, X.length can
> never change and the data pointed to by X.ptr can never change? Or is "can
> never" too strong? Is it more that code within the scope of the declaration
> is not allowed to change those things?

See the exception above. But now consider a function:

void say(const char[] data)
{
  ...
}

The bits of data are a private copy of say, so they can be changed discretionarily (if that's a word). But the bits pointed to by data do not belong to say, so they can't be written.

If say wants to be fancy, it can look like this:

void say(final const char[] data)
{
  ...
}

Then data can't be even rebound. The "final" being a storage class, it doesn't appear in the function signature (e.g., in the interface file).



Andrei
March 16, 2007
Don Clugston wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Bruno Medeiros wrote:
>>> What is the status of the experimental designs for the "storage classes" manipulation that Andrei and others where thinking of for D. The last I heard from it was Andrei's max suggestion from his max design challenge, however, I think that suggestion may suffer from some problems in regards to the "maxtype" requirement, plus it is wholly incomplete in regards to how storage classes interact between each other. Like Andrei said, what is a "const inout lazy const char[]", if valid at all? Is there any news here? Is there a working(aka complete) design?
>>
>> We have talked about a design. In short, the intent is to define three flavors of immutability:
>>
>> a) final - a simple storage class controlling the immutability of the bits allocated for the symbol per se;
>>
>> b) const - type qualifier meaning an immutable view of an otherwise modifiable data. const does not control the bits of the object, only the storage addressed indirectly by it (transitively);
>>
>> c) "superconst" - denoted as "const!" or "super const": type qualifier meaning that the data is genuinely unmodifiable.
> 
> Does this last category include some of the current use of D const -- a value which is not modifiable, *even in theory*, and may not even have any run-time existence at all -- the C equivalent being a #defined constant.

Yes.

> IMHO (b) should be 'readonly' and (c) should be 'const'.
> But this may be because I'm a physicist, and for me a constant is something like the speed of light, and C++'s const_cast always seemed utterly nonsensical.
> 
> void alabama() {  // Actually compiles! Someone should be shot for this.
>    const double PI = 3.14159265358;
>    *const_cast<double *>(&PI) = 4.0;
> }
> 
> Whereas 'readonly' seems to be a much better match for (b). Although it's an extra keyword, it seems to me that the concept discussed here is sufficiently fundamental to justify an extra keyword. Especially if we have a chance to rid of 'lazy'.

If we get rid of lazy, I'll sacrifice a lamb :o).

We've shoved keywords like "readonly" and "view" for a while, and they just added more confusion than cleared, at a high cost. If (as I suspect) super const appears relatively infrequently, it might be fine to just encode it as the mildly verbose "super const". In fact, it's shorter than "keepyourgrubbyhandsoff". :o)


Andrei
March 16, 2007
janderson wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Bruno Medeiros wrote:
>>> What is the status of the experimental designs for the "storage classes" manipulation that Andrei and others where thinking of for D. The last I heard from it was Andrei's max suggestion from his max design challenge, however, I think that suggestion may suffer from some problems in regards to the "maxtype" requirement, plus it is wholly incomplete in regards to how storage classes interact between each other. Like Andrei said, what is a "const inout lazy const char[]", if valid at all? Is there any news here? Is there a working(aka complete) design?
>>
>> We have talked about a design. In short, the intent is to define three flavors of immutability:
>>
>> a) final - a simple storage class controlling the immutability of the bits allocated for the symbol per se;
>>
>> b) const - type qualifier meaning an immutable view of an otherwise modifiable data. const does not control the bits of the object, only the storage addressed indirectly by it (transitively);
>>
>> c) "superconst" - denoted as "const!" or "super const": type qualifier meaning that the data is genuinely unmodifiable.
>>
>> There is talk about deprecating lazy if it's best implemented via other mechanisms. There is also talk about deprecating "inout" in favor of "ref" on grounds that the often-useful "inout const" is likely to become #1 reason for bashing D.
>>
>> To read a declaration like "const inout lazy const char[]", you can first parenthesize it appropriately:
>>
>> const(inout(lazy(const(char[]))))
>>
>> The lazy thing is really a delegate that returns a const char[]. The inout around it passes that delegate by reference, and the const at the top makes the delegate immutable.
>>
>>
>> Andrei
> 
> 
> Thanks for the update:
> 
> BTW:
> 
> const!(char[])
> 
> Looks to much like a template to me, I'd imagine some syntax phasers would have a harder time then necessary.

The damndest thing is that const! (as well as const) _is_ a template: it's a type constructor that takes another type as an argument and returns a type.

Andrei
March 16, 2007
Frits van Bommel wrote:
> Don Clugston wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> Bruno Medeiros wrote:
>>>> What is the status of the experimental designs for the "storage classes" manipulation that Andrei and others where thinking of for D. The last I heard from it was Andrei's max suggestion from his max design challenge, however, I think that suggestion may suffer from some problems in regards to the "maxtype" requirement, plus it is wholly incomplete in regards to how storage classes interact between each other. Like Andrei said, what is a "const inout lazy const char[]", if valid at all? Is there any news here? Is there a working(aka complete) design?
>>>
>>> We have talked about a design. In short, the intent is to define three flavors of immutability:
>>>
>>> a) final - a simple storage class controlling the immutability of the bits allocated for the symbol per se;
>>>
>>> b) const - type qualifier meaning an immutable view of an otherwise modifiable data. const does not control the bits of the object, only the storage addressed indirectly by it (transitively);
> 
> Presumably this can also be an immutable view of immutable (case c) data?

Yes, super const is trivially convertible to const. Const alone really means "I don't care about the nature of the data, I just promise I have no business writing into it".

>>> c) "superconst" - denoted as "const!" or "super const": type qualifier meaning that the data is genuinely unmodifiable.
>>
>> Does this last category include some of the current use of D const -- a value which is not modifiable, *even in theory*, and may not even have any run-time existence at all -- the C equivalent being a #defined constant.
>>
>> IMHO (b) should be 'readonly' and (c) should be 'const'.
> [snip]
>> Whereas 'readonly' seems to be a much better match for (b). Although it's an extra keyword, it seems to me that the concept discussed here is sufficiently fundamental to justify an extra keyword. Especially if we have a chance to rid of 'lazy'.
> 
> vote++;
> 
> 'const' should really means "constant". A new keyword is more than justified here.

We're doomed either way. We don't want to confuse C++ programmers. Two levels of strength of const are more descriptive than a new keyword that half of the people will think it's the other way.


Andrei
March 16, 2007
sclytrack wrote:
>> IMHO (b) should be 'readonly' and (c) should be 'const'.
> [snip]
> 
> vote++
> 
> 
> Keywords
> --------
> 
> I also think keywords can be written attached to one another.
> Like if you were to really call it "super const" have it called
> superconst instead of super_const.

Yet you write static const not staticconst; public static not publicstatic; static if and not staticif; and so on.

superconst came up too. But it creates a bad precedent. A healthier precedent is to synthesize phrases, not new keywords, from the existing keywords. Think of "static if" or "final switch". Very beautiful.

> It is like the foreach_reverse that we have in D. Why not
> call it foreachreverse instead.

Probably it's best to call it foreach reverse. It's unambiguous, easy to parse, does not add new keywords, and continues another nice precedent set by extern(language) and by scope(exit).


Andrei
March 16, 2007
eao197 wrote:
> On Fri, 16 Mar 2007 00:16:48 +0300, Andrei Alexandrescu (See Website For Email) <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> a) final - a simple storage class controlling the immutability of the bits allocated for the symbol per se;
>>
>> b) const - type qualifier meaning an immutable view of an otherwise modifiable data. const does not control the bits of the object, only the storage addressed indirectly by it (transitively);
>>
>> c) "superconst" - denoted as "const!" or "super const": type qualifier meaning that the data is genuinely unmodifiable.
> 
> Great!
> 
> What about the influence of this storage classes on class method's signatures? Is this will be in D:
> 
> class Data { ... }
> 
> class Container {
>   // non-const access to data.
>   Data data() { ... }
>   // const access to data.
>   const Data data() const { ... }
> }
> 
> void useContainer( const Container c ) {
>   auto d = c.data(); // the type of d is 'const Data'.
>   ...
> }
> 
> ?

Yes, that's part of the plan. Moreover, you'll likely have the ability to define const-transporting methods (methods that look identical but only need to pass the const of the object out to the return value) only once. This has been a source of annoyance in certain C++ idioms.


Andrei
March 16, 2007
On Fri, 16 Mar 2007 12:43:19 +0300, Andrei Alexandrescu (See Website For Email) <SeeWebsiteForEmail@erdani.org> wrote:

> Yes, that's part of the plan. Moreover, you'll likely have the ability to define const-transporting methods (methods that look identical but only need to pass the const of the object out to the return value) only once. This has been a source of annoyance in certain C++ idioms.

Thanks, I'm glad to hear that!

It seems that D with this storage classes and const-transporting methods will be almost different D, may be D 2.0 :)

-- 
Regards,
Yauheni Akhotnikau