Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 20, 2008 const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
//-------- BEGIN CODE EXAMPLE ------------
class C{ int val; }
void main()
{
// 'c' is an implied const reference to a const object
const(C) c = new C;
const(C) d = new C;
c = d; // fails "variable test.main.c cannot modify const"
c.val = 1; // fails "Error: cannot modify const/invariant c.val"
// 'cc' is a const reference to an implied const object
const C cc = new C;
const C dd = new C;
cc = dd; // fails "variable test.main.cc cannot modify const"
cc.val = 1; // fails "Error: cannot modify const/invariant cc.val"
// 'ccc' is a mutable reference to a mutable object
C ccc = new C;
const C ddd = new C;
ccc = ddd; // fails "Error: cannot implicitly convert expression (ddd)
of type const(C) to test.C"
ccc.val = 1; // allowed
ddd = ccc; // fails "variable test.main.ddd cannot modify const"
// 'e' is a const value
const(char) e = 'a';
const(char) f = 'b';
f = e; // fails "variable test.main.f cannot modify const"
// 'g' is a mutable reference to an array of const data
const(char)[] g = "abc";
const(char)[] h = "xyz";
h = g; // Allowed!!!
h[0] = 'A'; // fails "Error: h[0] is not mutable"
// 'gg' is a const reference to an array of const data
const const(char)[] gg = "abc";
const const(char)[] hh = "xyz"; // fails?? " Error: hh[0] is not
mutable"
hh = gg; // fails "variable test.main.hh cannot modify const"
hh[0] = 'A'; // fails "Error: constant hh[0] is not an lvalue"???
// ??? 'i' is a const reference to an array of const data ???
const(char[]) i = "abc";
const(char[]) j = "xyz"; // ?? FAILS "Error: j[0] is not mutable"
j = i; // fails "variable test.main.j cannot modify const"
j[0] = 'A'; // fails "Error: constant j[0] is not an lvalue" ????
}
//------------ END CODE EXAMPLE ------------
Observations:
** It appears that there is no practical difference between 'const(C) c'
and 'const C c'.
** It appears that 'const(char[])' and 'const const(char)[]' are equivalent
and also not implemented well (or the error messages are just bad).
** The addition of '[]' changes the meaning of the syntax form 'const(x)
y'. Specifically 'const(x) y' means that the bits in 'y' are immutable but
'const(x)[] y' means that the bits in 'y' are mutable.
** The current implementation of const in dmd v2.011 is definitely confusing, and is not as regular/orthogonal as I expected it to be.
** There are some access permutations that are not possible without deceiving the compiler. This has got to be a bad thing for maintenance costs.
--
Derek
(skype: derek.j.parnell)
Melbourne, Australia
21/02/2008 10:11:53 AM
|
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | 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. 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. > ** It appears that 'const(char[])' and 'const const(char)[]' are > equivalent and also not implemented well (or the error messages are just > bad). const(char)[] means the char's within the array can't be changed, but the array itself can change (ie. length changes, concatenation) |
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jason House | 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. >> ** It appears that 'const(char[])' and 'const const(char)[]' are >> equivalent and also not implemented well (or the error messages are just >> bad). > > 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. also this ... const(char)* k; // 'k' is a mutable pointer to immutable data. const(char*) l; // 'l' is an immutable pointer to immutable data. The forms 'const(char)[]' and 'const(char)*' ignore transitivity while other forms enforce it. It could be confusing, no? Also the forms 'const const(X)[]', 'const const(X[])', and 'const(X[])' appear to be synonymous, another way to confuse people. -- Derek (skype: derek.j.parnell) Melbourne, Australia 21/02/2008 11:22:35 AM |
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | On Thu, 21 Feb 2008 11:44:14 +1100, 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.
>
>>> ** It appears that 'const(char[])' and 'const const(char)[]' are
>>> equivalent and also not implemented well (or the error messages are
>>> just bad).
>>
>> 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.
>
> also this ...
>
> const(char)* k; // 'k' is a mutable pointer to immutable data.
> const(char*) l; // 'l' is an immutable pointer to immutable data.
>
> The forms 'const(char)[]' and 'const(char)*' ignore transitivity while
> other forms enforce it. It could be confusing, no?
>
> Also the forms 'const const(X)[]', 'const const(X[])', and 'const(X[])'
> appear to be synonymous, another way to confuse people.
Personally the const(char)* and const(char)[] make sense in their meaning. Not too the definition given of transivity:
"transitive, which means that any data reachable through an invariant reference is also invariant, and likewise for const."
The use of the word reference shows that it does not apply to pointers. This however is confusing to those that do not see a difference, I do it my self at times.
|
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | 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. I don't see the confusion. I've previously argued that "const(C) c" and "const C c" should mean the same thing. The whole distinction between a type and a storage class seemed foreign and strange to me. >>> ** It appears that 'const(char[])' and 'const const(char)[]' are >>> equivalent and also not implemented well (or the error messages are just >>> bad). >> >> 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. Sorry. It's tough to know what people know, and it's usually best to elimate the simple stuff first ;) > 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. > > also this ... > > const(char)* k; // 'k' is a mutable pointer to immutable data. > const(char*) l; // 'l' is an immutable pointer to immutable data. > > The forms 'const(char)[]' and 'const(char)*' ignore transitivity while > other forms enforce it. It could be confusing, no? I've already admitted that I'm biased :) It seems easy to explain to me: * Anything inside parenthesis is constant * Const is transitive. Any data access through a const reference is const. * "const T t" is the same as "const(T) t" > Also the forms 'const const(X)[]', 'const const(X[])', and 'const(X[])' > appear to be synonymous, another way to confuse people. I totally agree with that. Literally typed like that seems like it should be illegal. I can imagine complex cases where something like that should be legal... eg: alias const(X) Y; const Y z; |
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | "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 |
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | "Steven Schveighoffer" wrote
>> 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.
I didn't say this right. What I meant was
Transitivity means that if you have a pointer who defines itself as pointing to const data, any data that you access through that pointer, whether it be the data the pointer points to, or data pointed to by the const data, must be const.
For example:
int z = 1;
int * y = &z;
const(int*)* x = &y;
writefln(**x); // outputs 1, this is ok because i'm just reading the data,
not modifying
*y = 2;
writefln(**x); // outputs 2, still ok, because I'm not modifying
**x = 3; // not ok, even though y isn't const, I'm trying to modify what y
points to *through* x.
I hope this helps.
-Steve
|
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Wed, 20 Feb 2008 22:39:03 -0500, Steven Schveighoffer wrote: > 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. After a bit more examination, it is probably not a bug but just a poor error message. It turns out that const(char[]) s = "abc"; is essentially treated as a manifest constant. It is almost identical to enum (s = "abc"} The person who can document all this 'const' implementation so that most people can grasp it and remember it, will win lots of brownie points. -- Derek (skype: derek.j.parnell) Melbourne, Australia 21/02/2008 5:42:22 PM |
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | "Derek Parnell" wrote > On Wed, 20 Feb 2008 22:39:03 -0500, Steven Schveighoffer wrote: > >> 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. > > After a bit more examination, it is probably not a bug but just a poor error message. It turns out that > > const(char[]) s = "abc"; > > is essentially treated as a manifest constant. It is almost identical to > > enum (s = "abc"} Well, the lines I was thinking of were (from your original post): const(char[]) i = "abc"; const(char[]) j = "xyz"; // ?? FAILS "Error: j[0] is not mutable" Why does i work, but j does not? Both lines seem identical in syntax. Besides that, a string (which is an invariant(char)[]) should be assingable to a const, because you can implicitly cast the mutable array to a const array, and implictly cast an invariant char to a const char (for the element type). So I would expect both i and j to compile. > > The person who can document all this 'const' implementation so that most people can grasp it and remember it, will win lots of brownie points. > I think the tough part to grasp right now is the 'why' not the 'how'. Once people stop debating the why part, the how becomes as simple as a set of examples and explanation of how to use it. -Steve |
February 21, 2008 Re: const in dmd v2.011 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thu, 21 Feb 2008 09:05:15 -0500, Steven Schveighoffer wrote: > "Derek Parnell" wrote >> On Wed, 20 Feb 2008 22:39:03 -0500, Steven Schveighoffer wrote: >> >>> 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. >> >> After a bit more examination, it is probably not a bug but just a poor error message. It turns out that >> >> const(char[]) s = "abc"; >> >> is essentially treated as a manifest constant. It is almost identical to >> >> enum (s = "abc"} > > Well, the lines I was thinking of were (from your original post): > const(char[]) i = "abc"; > const(char[]) j = "xyz"; // ?? FAILS "Error: j[0] is not mutable" > > Why does i work, but j does not? Both lines seem identical in syntax. They are identical but the compiler is a bit too smart. The first one compiles without complaint because the 'manifest' constant it declares is never actually used so it optimizes it out of the picture. The second ones 'fails' to compile because I attempt to use 'j' as an lvalue later on. The error message is very misleading, but accurate too. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell |
Copyright © 1999-2021 by the D Language Foundation