digitalmars.D - about the new const regime
- Daniel919 (34/34) Jan 01 2008 (dmd 2.009)
- Janice Caron (20/27) Jan 01 2008 You can do
- davidl (8/42) Jan 02 2008 The difference is :
- Daniel919 (8/14) Jan 02 2008 But the same is true for a const(char)[].
- Steven Schveighoffer (21/35) Jan 02 2008 The difference is subtle. invariant means "nothing can change this". c...
- Daniel919 (14/42) Jan 02 2008 .. from this pointer/ref.
- Steven Schveighoffer (19/39) Jan 02 2008 c is not a copy of s or a reference to s. c references the same data th...
- Daniel919 (11/34) Jan 02 2008 writefln( c ); //test
- Dan (6/15) Jan 02 2008 The difference being that the compiler is allowed to optimize an invaria...
- Daniel919 (57/62) Jan 02 2008 There is a little difference:
- Bruce Adams (4/9) Jan 02 2008 My initial thought is oh no not again. It would be more productive to
- Oskar Linde (13/26) Jan 04 2008 I fully agree. The actual keywords are secondary to the semantics (of
- Sascha Katzner (9/12) Jan 04 2008 I like this idea to exchange the meaning of const and invariant *VERY*
(dmd 2.009) What's the difference between "const T" and "invariant T", if T is a value type (builtin type or struct)? Value types are always a copy and never refer to anything. So a const(T) can't be changed. Example: typeid(string) == "invariant(char)[]" (default) string s = "bla"; s[0] = 'x'; //Error, cannot change a invariant(char) But then, where is the difference to const(char)? If there really is no difference, shouldn't string be "const(char)[]" then? And maybe invariant(T) should be an error, when T is a valuetype? About enum: Instead of the current "abuse" of enum to also define values that take no space, I would like a new keyword, which can be used more general: meta metaprogramming <=> compile time programming meta <=> compile time meta x = 1; <=> meta int x = 1; x is a compile time value of type int. enum { red, green, blue } //<=> meta red = 0, green = 1, blue = 2; This could also help to make a better distinction: class Foo { static int x; } means x is not bound to an object. using static this(), x can be assigned at runtime static if( ... ) ... means evaluate the if at compile time With the new keyword, it could be renamed to meta if( ... ) ... static <=> not bound to an object meta <=> compile time Best regards and happy new year, Daniel
Jan 01 2008
On 1/1/08, Daniel919 <Daniel919 web.de> wrote:(dmd 2.009) What's the difference between "const T" and "invariant T", if T is a value type (builtin type or struct)?Pretty much none. In both cases, the type is invariant in practice.If there really is no difference, shouldn't string be "const(char)[]" then? And maybe invariant(T) should be an error, when T is a valuetype?You can do const x = 5; invariant x = 5; If the compiler is smart enough, in both cases, x will have type invariant(int). If the compiler doesn't try to be smart, then x will have type const(int) and invariant(int) respectively. Having two ways to say the same thing may seem redundant, but for reasons of generic programming, neither of them should be considered an error.enum { red, green, blue } //<=> meta red = 0, green = 1, blue = 2;For those of us who support "real enums", those two are not equivalent, since "real enums" make no numerical value available to the programmer. You have no choice /but/ to use the enumerated names. But of course, for that very reason, many (myself included) have argued that a different keyword for manifest constants would be a good idea (possibly paving the way for "enum" to be retooled to make "real enums" in the future). "meta" is as good a name as any, although I think I like "manifest" better. I'd be happy with either. But right now, neither is on the table.
Jan 01 2008
在 Wed, 02 Jan 2008 01:14:22 +0800,Daniel919 <Daniel919 web.de> 写道:(dmd 2.009) What's the difference between "const T" and "invariant T", if T is a value type (builtin type or struct)? Value types are always a copy and never refer to anything. So a const(T) can't be changed. Example: typeid(string) == "invariant(char)[]" (default) string s = "bla"; s[0] = 'x'; //Error, cannot change a invariant(char) But then, where is the difference to const(char)?The difference is : string s = "bla"; s = "abc"; // compile, you can reassign to an invariant array with another invariant array, but you can't change it partially. s[0] = 'x'; //error as you saidIf there really is no difference, shouldn't string be "const(char)[]" then? And maybe invariant(T) should be an error, when T is a valuetype? About enum: Instead of the current "abuse" of enum to also define values that take no space, I would like a new keyword, which can be used more general: meta metaprogramming <=> compile time programming meta <=> compile time meta x = 1; <=> meta int x = 1; x is a compile time value of type int. enum { red, green, blue } //<=> meta red = 0, green = 1, blue = 2; This could also help to make a better distinction: class Foo { static int x; } means x is not bound to an object. using static this(), x can be assigned at runtime static if( ... ) ... means evaluate the if at compile time With the new keyword, it could be renamed to meta if( ... ) ... static <=> not bound to an object meta <=> compile time Best regards and happy new year, Daniel-- 使用 Opera 革命性的电子邮件客户程序: http://www.opera.com/mail/
Jan 02 2008
The difference is : string s = "bla"; s = "abc"; // compile, you can reassign to an invariant array with another invariant array, but you can't change it partially. s[0] = 'x'; //error as you saidBut the same is true for a const(char)[]. const(char)[] s = "bla"; s = "abc"; s[0] = 'x'; //error const char[] s = "bla"; s = "abc" //error invariant char[] s = "bla"; s = "abc" //error
Jan 02 2008
"Daniel919" wroteThe difference is subtle. invariant means "nothing can change this". const means "I can't change this". So for a const array, for instance: char[] s = "bla".dup; const(char)[] c = s; // ok invariant(char)[] i = s; // error invariant(char)[] i2 = c; // error This is an error because since you could potentially change i by changing s, you can't assign s to i or c to i without an explicit cast. The explicit cast tells the compiler you are ensuring that s will no longer be changed by anything: invariant(char)[] i3 = cast(invariant(char)[])s; // ok This is ok, but you can no longer change s. If you do, the behavior is undefined. Do you see the difference now? In most cases, if you are initializing a const variable with a literal, or a new() statement, you can change the modifier to invariant because logically, nothing can change that variable. It would be nice if the compiler automatically did this for you, but I don't think this is the case today. -SteveThe difference is : string s = "bla"; s = "abc"; // compile, you can reassign to an invariant array with another invariant array, but you can't change it partially. s[0] = 'x'; //error as you saidBut the same is true for a const(char)[]. const(char)[] s = "bla"; s = "abc"; s[0] = 'x'; //error const char[] s = "bla"; s = "abc" //error invariant char[] s = "bla"; s = "abc" //error
Jan 02 2008
The difference is subtle. invariant means "nothing can change this". const means "I can't change this"... from this pointer/ref. So I can read this only from this pointer/ref. Ok, I already posted some thoughts about it under this topic.So for a const array, for instance: char[] s = "bla".dup; const(char)[] c = s; // ok invariant(char)[] i = s; // error invariant(char)[] i2 = c; // error This is an error because since you could potentially change i by changing s,Tried it: char[] s = "bla".dup; const(char)[] c = s; writefln( c ); //bla s = "new".dup; writefln( c ); //bla So c got a copy of s. But then, how can I change c by using s? If I can't, then I see no difference to invariant(char)[]. If c was a reference to s, then it would make sense to distinct between: 1. can't change the data of c via c = const(char)[] 2. data of c will never change = invariant(char)[]you can't assign s to i or c to i without an explicit cast. The explicit cast tells the compiler you are ensuring that s will no longer be changed by anything: invariant(char)[] i3 = cast(invariant(char)[])s; // ok This is ok, but you can no longer change s. If you do, the behavior is undefined. Do you see the difference now? In most cases, if you are initializing a const variable with a literal, or a new() statement, you can change the modifier to invariant because logically, nothing can change that variable. It would be nice if the compiler automatically did this for you, but I don't think this is the case today. -Steve
Jan 02 2008
"Daniel919" wrotec is not a copy of s or a reference to s. c references the same data that s references. When you change s to reference different data, it does not change c to reference this data. i.e. after the assignment, s.ptr != c.ptr. Maybe this example will help: int x = 5; int *p = &x; int *p2 = p; writefln(*p, *p2); // outputs 55 int y = 6; p = &y; writefln(*p, *p2); // outputs 65 Assigning p to &y is similar to your code assigning s to "new".dup; Now, if you modified a piece of the data s is pointing to, then c will change. Try this: s[0..3] = "new"; This copies the data from the array on the right into the array on the left (I didn't yet compile this, so I'm not sure if it compiles as coded). -SteveSo for a const array, for instance: char[] s = "bla".dup; const(char)[] c = s; // ok invariant(char)[] i = s; // error invariant(char)[] i2 = c; // error This is an error because since you could potentially change i by changing s,Tried it: char[] s = "bla".dup; const(char)[] c = s; writefln( c ); //bla s = "new".dup; writefln( c ); //bla So c got a copy of s. But then, how can I change c by using s? If I can't, then I see no difference to invariant(char)[]. If c was a reference to s, then it would make sense to distinct between: 1. can't change the data of c via c = const(char)[] 2. data of c will never change = invariant(char)[]
Jan 02 2008
c is not a copy of s or a reference to s. c references the same data that s references. When you change s to reference different data, it does not change c to reference this data. i.e. after the assignment, s.ptr != c.ptr. Maybe this example will help: int x = 5; int *p = &x; int *p2 = p; writefln(*p, *p2); // outputs 55 int y = 6; p = &y; writefln(*p, *p2); // outputs 65 Assigning p to &y is similar to your code assigning s to "new".dup; Now, if you modified a piece of the data s is pointing to, then c will change. Try this: s[0..3] = "new"; This copies the data from the array on the right into the array on the left (I didn't yet compile this, so I'm not sure if it compiles as coded).writefln( c ); //test s[0..3] = "new"; writefln( c ); //newt This made it clear, shows that c is not a copy of s. And as expected: c[0..3] = "new";//Error: slice c[cast(uint)0..cast(uint)3] is not mutable const(char)[] c = s; elements c refers to can't be changed via c invariant(char)[] i = s; elements i refers to will never change Thanks for your explanation.
Jan 02 2008
Steven Schveighoffer Wrote:"Daniel919" wroteThe difference being that the compiler is allowed to optimize an invariant under the assumption that it won't ever *be* changed may entail caching results of evaluating it, and other similar optimizations. Lemma 1) accepting that our algorithms are incorrect if changed by influences outside our control. This lemma is inherent to all programs though. One cannot control the environment on which they run. Sure, we can perform sanity checks, but even bootloaders and OS's are run on emulators and can be influenced in unexpected ways. I would therefore suggest that everything that is const within an entire program is therefore inherently invariant for our purposes. Regards, Danconst char[] s = "bla"; s = "abc" //error invariant char[] s = "bla"; s = "abc" //errorThe difference is subtle. invariant means "nothing can change this". const means "I can't change this".
Jan 02 2008
What's the difference between "const T" and "invariant T", if T is a value type (builtin type or struct)? Value types are always a copy and never refer to anything. So a const(T) can't be changed.There is a little difference: struct St { T ptr2sth; } //T is a class or a pointer to sth const St st = St(&sth); st.ptr2sth is an invariant ptr to: sth that might change invariant St st = St(&someobj); st.ptr2sth is an invariant ptr to: sth that will never change However, const(valuetype) is always equivalent to invariant(valuetype) That's also why: const Foo* ptr2foo; a const ptr to a const Foo <=> an invariant ptr to a const Foo So the distinction between const and invariant is only important, when it comes to the question, what a ptr is pointing to: 1. const(Foo)* ptr2constfoo = &foo; 2. invariant(Foo)* ptr2invariantfoo = &foo; My opinion is that const reads like: this will never change I know there is no difference between const,invariant,readonly,immutable,... in the English language. And that in C++ const also doesn't mean "this will never change". But I think, the best fitting one to express what we really want in case 1 is: readonly Because it stands for what we intend to do: Use this ptr to read Foo only. So a ptr to sth readonly means: readonlyview AND NOT: ptr to readonly data (just like function params in,inout,out express what we intend to do) Of course one could argue that readonly reads like: this Foo is readonly and thus will never change. But for const it's the other way round: I argue that const reads like: this Foo is const and thus will never change And not that it means: we can only read this Foo from this ptr (but it might get changed from somewhere) It's the problem that all these words are synonyms in the English language. But I can better live with: readonly(T)* to mean: ptr that is used to read only and NOT to mean: ptr to sth that will never change than const(T)* to mean: ptr that is used to read only and NOT to mean: ptr to sth that will never change This way const T foo = ...; would mean that nothing of foo will ever change. With the current system, you would have to use invariant. But then, for consistency, you should not use "const x = 1;" but "invariant x = 1;" So you would mostly use invariant, and const only where you want to say: ptr that is used to read only But then it would be easier if we change: const to readonly invariant to const You can give it a try, just compile like: cat ./test.d | sed -e 's/const/invariant/g;s/readonly/const/g' > test2.d && dmd.exe test2.d | sed -e 's/const/readonly/g;s/invariant/const/g' && ./test2 Best regards, Daniel
Jan 02 2008
On Wed, 02 Jan 2008 14:25:59 -0000, Daniel919 <Daniel919 web.de> wrote:My opinion is that const reads like: this will never change I know there is no difference between const,invariant,readonly,immutable,... in the English language. And that in C++ const also doesn't mean "this will never change".My initial thought is oh no not again. It would be more productive to leave thoughts about syntax to one side until the semantics are thoroughly clear to everyone.
Jan 02 2008
Bruce Adams wrote:On Wed, 02 Jan 2008 14:25:59 -0000, Daniel919 <Daniel919 web.de> wrote:I fully agree. The actual keywords are secondary to the semantics (of course), but in this case, I think we may experience something similar to the Stroop effect in psychology. Imagine trying to explain the colors of a painting to someone, but insisting on using the word "red" to mean blue and "blue" to mean red. Of all the "synonyms" above, "constant" is the one understood by most people. Unfortunately, the D keyword "const" doesn't mean constant -- it means something different and another keyword means constant. This fact can't be very helpful in making the semantics thoroughly clear to everyone. :) -- OskarMy opinion is that const reads like: this will never change I know there is no difference between const,invariant,readonly,immutable,... in the English language. And that in C++ const also doesn't mean "this will never change".My initial thought is oh no not again. It would be more productive to leave thoughts about syntax to one side until the semantics are thoroughly clear to everyone.
Jan 04 2008
Daniel919 wrote:But then it would be easier if we change: const to readonly invariant to constI like this idea to exchange the meaning of const and invariant *VERY* much. Personally I prefer "invariant" to "readonly", but this is negligible. The very nice side effect of this change would be, that we could kick the recent enum changes (which practically nobody likes *eg*), in favor to the much more intuitive and backward compatible "const PI = 3.14" form for manifest constants. LLAP, Sascha Katzner
Jan 04 2008