www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - const question/suggestion

reply "Craig Black" <cblack ara.com> writes:
OK, I think I'm starting to grasp the subtle differences between const, 
final, and invariant.  It seems to me that to have three keywords is 
unnecessary.  Perhaps const and final could be merged into one?

From my understanding, the only difference between const and final is that 
local final fields can be initialized in a constructor, right?  Couldn't 
that just be the default behavior of a local const field?  Then we could get 
rid of final and have only two keywords.  Or am I missing something?  IMO, 
two keywords is way less confusing than three.

Another question.  Since invariant data should always be invariant, does it 
make sense to be able to cast non-invariant data to invariant?  The compiler 
will think that it is invariant when it isn't.

-Craig 
Jun 18 2007
next sibling parent Sean Kelly <sean f4.ca> writes:
Craig Black wrote:
 OK, I think I'm starting to grasp the subtle differences between const, 
 final, and invariant.  It seems to me that to have three keywords is 
 unnecessary.  Perhaps const and final could be merged into one?
Funny, I was going to say that about 'final' and 'invariant'. So far as I can tell, the only difference between them from a user perspective is that 'invariant' is transitive while 'final' is not. The ROMability of 'invariant' is a compiler issue and is meaningless to the user.
 From my understanding, the only difference between const and final is that 
 local final fields can be initialized in a constructor, right?  Couldn't 
 that just be the default behavior of a local const field?  Then we could get 
 rid of final and have only two keywords.  Or am I missing something?  IMO, 
 two keywords is way less confusing than three.
That was my thought as well.
 Another question.  Since invariant data should always be invariant, does it 
 make sense to be able to cast non-invariant data to invariant?  The compiler 
 will think that it is invariant when it isn't.
This is probably just a matter of not making special cases for the compiler. Casts are always allowed, even those that don't make sense. Sean
Jun 18 2007
prev sibling next sibling parent reply Myron Alexander <someone somewhere.com> writes:
Craig Black wrote:
 OK, I think I'm starting to grasp the subtle differences between const, 
 final, and invariant.  It seems to me that to have three keywords is 
 unnecessary.  Perhaps const and final could be merged into one?
 
 From my understanding, the only difference between const and final is that 
 local final fields can be initialized in a constructor, right?  Couldn't 
 that just be the default behavior of a local const field?  Then we could get 
 rid of final and have only two keywords.  Or am I missing something?  IMO, 
 two keywords is way less confusing than three.
 
 Another question.  Since invariant data should always be invariant, does it 
 make sense to be able to cast non-invariant data to invariant?  The compiler 
 will think that it is invariant when it isn't.
 
 -Craig 
 
 
Craig, const and final have two very different roles. Const ensures that the value referenced/pointed to by the reference/pointer cannot be changed. In other words, if an object reference is bound to a const variable, then the object is immutable when referenced via that variable. Final is different in that it prevents a variable from having another value bound to it. In other words, if you have a reference variable, once initialised, you cannot assign a new reference to the variable. Examples: SomeObject is a mutable class, IE it's value can be modified. auto mutvar = new SomeObject (); mutvar.changesomething() -- ok const var = new SomeObject (); var.changesomething() -- fails Now for final: final finvar = new SomeObject (); -- ok finvar.changesomething() -- ok ... finvar = new SomeObject (); -- fails Regards, Myron.
Jun 18 2007
next sibling parent Myron Alexander <someone somewhere.com> writes:
Myron Alexander wrote:
 Craig Black wrote:
 OK, I think I'm starting to grasp the subtle differences between 
 const, final, and invariant.  It seems to me that to have three 
 keywords is unnecessary.  Perhaps const and final could be merged into 
 one?

 From my understanding, the only difference between const and final is 
 that local final fields can be initialized in a constructor, right?  
 Couldn't that just be the default behavior of a local const field?  
 Then we could get rid of final and have only two keywords.  Or am I 
 missing something?  IMO, two keywords is way less confusing than three.

 Another question.  Since invariant data should always be invariant, 
 does it make sense to be able to cast non-invariant data to 
 invariant?  The compiler will think that it is invariant when it isn't.

 -Craig
Craig, const and final have two very different roles. Const ensures that the value referenced/pointed to by the reference/pointer cannot be changed. In other words, if an object reference is bound to a const variable, then the object is immutable when referenced via that variable. Final is different in that it prevents a variable from having another value bound to it. In other words, if you have a reference variable, once initialised, you cannot assign a new reference to the variable. Examples: SomeObject is a mutable class, IE it's value can be modified. auto mutvar = new SomeObject (); mutvar.changesomething() -- ok const var = new SomeObject (); var.changesomething() -- fails Now for final: final finvar = new SomeObject (); -- ok finvar.changesomething() -- ok ... finvar = new SomeObject (); -- fails Regards, Myron.
Oops, forgot to add this:
 const var = new SomeObject ();
 var.changesomething() -- fails
var = new SomeObject (); -- ok Regards, Myron.
Jun 18 2007
prev sibling next sibling parent "Craig Black" <cblack ara.com> writes:
OK, didn't catch that.  Thanks.

"Myron Alexander" <someone somewhere.com> wrote in message 
news:f569rr$22n9$1 digitalmars.com...
 Craig Black wrote:
 OK, I think I'm starting to grasp the subtle differences between const, 
 final, and invariant.  It seems to me that to have three keywords is 
 unnecessary.  Perhaps const and final could be merged into one?

 From my understanding, the only difference between const and final is 
 that local final fields can be initialized in a constructor, right? 
 Couldn't that just be the default behavior of a local const field?  Then 
 we could get rid of final and have only two keywords.  Or am I missing 
 something?  IMO, two keywords is way less confusing than three.

 Another question.  Since invariant data should always be invariant, does 
 it make sense to be able to cast non-invariant data to invariant?  The 
 compiler will think that it is invariant when it isn't.

 -Craig
Craig, const and final have two very different roles. Const ensures that the value referenced/pointed to by the reference/pointer cannot be changed. In other words, if an object reference is bound to a const variable, then the object is immutable when referenced via that variable. Final is different in that it prevents a variable from having another value bound to it. In other words, if you have a reference variable, once initialised, you cannot assign a new reference to the variable. Examples: SomeObject is a mutable class, IE it's value can be modified. auto mutvar = new SomeObject (); mutvar.changesomething() -- ok const var = new SomeObject (); var.changesomething() -- fails Now for final: final finvar = new SomeObject (); -- ok finvar.changesomething() -- ok ... finvar = new SomeObject (); -- fails Regards, Myron.
Jun 18 2007
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Myron Alexander wrote:
 const var = new SomeObject ();
The above line will fail because const declarations can only be initialized with something that can be evaluated at compile time. The example should be: const(SomeObject) var = new SomeObject();
 var.changesomething() -- fails
Jun 18 2007
next sibling parent Myron Alexander <someone somewhere.com> writes:
Walter Bright wrote:
 Myron Alexander wrote:
 const var = new SomeObject ();
The above line will fail because const declarations can only be initialized with something that can be evaluated at compile time. The example should be: const(SomeObject) var = new SomeObject();
 var.changesomething() -- fails
Thanks for the correction. Regards, Myron.
Jun 18 2007
prev sibling next sibling parent reply James Dennett <jdennett acm.org> writes:
Walter Bright wrote:
 Myron Alexander wrote:
 const var = new SomeObject ();
The above line will fail because const declarations can only be initialized with something that can be evaluated at compile time. The example should be: const(SomeObject) var = new SomeObject();
Is there any way to use type deduction to avoid having to repeat the SomeObject part of this? -- James
Jun 18 2007
next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
James Dennett wrote:
 Walter Bright wrote:
 Myron Alexander wrote:
 const var = new SomeObject ();
The above line will fail because const declarations can only be initialized with something that can be evaluated at compile time. The example should be: const(SomeObject) var = new SomeObject();
Is there any way to use type deduction to avoid having to repeat the SomeObject part of this? -- James
auto var = cast(const) new SomeObject(); It's one character shorter :P -- Daniel
Jun 18 2007
prev sibling parent Reiner Pope <some address.com> writes:
James Dennett wrote:
 Walter Bright wrote:
 Myron Alexander wrote:
 const var = new SomeObject ();
The above line will fail because const declarations can only be initialized with something that can be evaluated at compile time. The example should be: const(SomeObject) var = new SomeObject();
Is there any way to use type deduction to avoid having to repeat the SomeObject part of this? -- James
It seems like something like that should be plausible. How about: const() var = new SomeObject(); // --> const(SomeObject) var; const var2 = new SomeObject(); // --> const SomeObject var; -- Reiner
Jun 18 2007
prev sibling parent reply "Kristian Kilpi" <kjkilpi gmail.com> writes:
On Tue, 19 Jun 2007 00:55:21 +0300, Walter Bright  =

<newshound1 digitalmars.com> wrote:

 Myron Alexander wrote:
 const var =3D new SomeObject ();
The above line will fail because const declarations can only be =
 initialized with something that can be evaluated at compile time. The =
=
 example should be:

 	const(SomeObject) var =3D new SomeObject();

 var.changesomething() -- fails
Now I'm a bit confused... Oh, now I get it. (I hope.) There can be constant views and constant, or literal, data. And literals= = are, of course, compile time, er, constants. Sometimes 'const' means immutable and sometimes it means literal, compil= e = time value... At first I read: const foo =3D new Bar; //or const Bar foo =3D new Bar; as: final const(Bar) foo =3D new Bar; That is, a final, constant view to an object (or, immutable reference = (final variable) + immutable object (constant view).) Not as a constant = = view to a constant/literal object. With value types, final will be sufficient: final int v =3D foo(); But with reference types, one must write "final const(...)"...? Uh, that= 's = verbose. :/ With functions, you can write: void f(const Bar foo); f(new Bar); //no need for compile time constant/literal Ok, inside the function, 'foo' will be treated as a constant/literal, so= = it makes sense, kind of. (And const-by-default function paramters are too inconsistent?... ;) ) Maybe I should also wonder this: how one can create an object that will = be = treated as invariant/constant? invariant Bar foo =3D new Bar; //global variable; currently inline = initialization not allowed though void f() { invariant obj =3D foo; } Surely the object pointed by 'foo' will be invariant during the executio= n = of the program.
Jun 19 2007
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Kristian Kilpi wrote:
 On Tue, 19 Jun 2007 00:55:21 +0300, Walter Bright 
 <newshound1 digitalmars.com> wrote:
 
 Myron Alexander wrote:
 const var = new SomeObject ();
The above line will fail because const declarations can only be initialized with something that can be evaluated at compile time. The example should be: const(SomeObject) var = new SomeObject();
 var.changesomething() -- fails
Now I'm a bit confused... Oh, now I get it. (I hope.) There can be constant views and constant, or literal, data. And literals are, of course, compile time, er, constants. Sometimes 'const' means immutable and sometimes it means literal, compile time value... At first I read: const foo = new Bar; //or const Bar foo = new Bar; as: final const(Bar) foo = new Bar; That is, a final, constant view to an object (or, immutable reference (final variable) + immutable object (constant view).) Not as a constant view to a constant/literal object. With value types, final will be sufficient: final int v = foo(); But with reference types, one must write "final const(...)"...? Uh, that's verbose. :/ With functions, you can write: void f(const Bar foo); f(new Bar); //no need for compile time constant/literal Ok, inside the function, 'foo' will be treated as a constant/literal, so it makes sense, kind of. (And const-by-default function paramters are too inconsistent?... ;) ) Maybe I should also wonder this: how one can create an object that will be treated as invariant/constant? invariant Bar foo = new Bar; //global variable; currently inline initialization not allowed though void f() { invariant obj = foo; } Surely the object pointed by 'foo' will be invariant during the execution of the program.
It has already been mentioned that you can 'cast(const) new Foo' to make it be treated as such (since you've cast it immediately upon creation, so there's no mutable referance available). Likewise with 'cast(invariant)'. I'm thinking these might be relatively common operations for some, so maybe it would be wise/better/convenient to allow these keywords between 'new' and 'Foo' like 'new const Foo'. If nothing else, it reads well to me, and provides type deduction. auto mvar = new Foo ; // Foo mvar ; auto cvar = new const Foo ; // const (Foo) cvar ; auto ivar = new invariant Foo ; // invariant(Foo) ivar ; final fvar = new const Foo ; // final const (Foo) fvar ; -- Chris Nicholson-Sauls
Jun 19 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Chris Nicholson-Sauls wrote:
 Kristian Kilpi wrote:
 On Tue, 19 Jun 2007 00:55:21 +0300, Walter Bright 
 <newshound1 digitalmars.com> wrote:

 Myron Alexander wrote:
 const var = new SomeObject ();
The above line will fail because const declarations can only be initialized with something that can be evaluated at compile time. The example should be: const(SomeObject) var = new SomeObject();
 var.changesomething() -- fails
Now I'm a bit confused... Oh, now I get it. (I hope.) There can be constant views and constant, or literal, data. And literals are, of course, compile time, er, constants. Sometimes 'const' means immutable and sometimes it means literal, compile time value... At first I read: const foo = new Bar; //or const Bar foo = new Bar; as: final const(Bar) foo = new Bar; That is, a final, constant view to an object (or, immutable reference (final variable) + immutable object (constant view).) Not as a constant view to a constant/literal object. With value types, final will be sufficient: final int v = foo(); But with reference types, one must write "final const(...)"...? Uh, that's verbose. :/ With functions, you can write: void f(const Bar foo); f(new Bar); //no need for compile time constant/literal Ok, inside the function, 'foo' will be treated as a constant/literal, so it makes sense, kind of. (And const-by-default function paramters are too inconsistent?... ;) ) Maybe I should also wonder this: how one can create an object that will be treated as invariant/constant? invariant Bar foo = new Bar; //global variable; currently inline initialization not allowed though void f() { invariant obj = foo; } Surely the object pointed by 'foo' will be invariant during the execution of the program.
It has already been mentioned that you can 'cast(const) new Foo' to make it be treated as such (since you've cast it immediately upon creation, so there's no mutable referance available). Likewise with 'cast(invariant)'. I'm thinking these might be relatively common operations for some, so maybe it would be wise/better/convenient to allow these keywords between 'new' and 'Foo' like 'new const Foo'. If nothing else, it reads well to me, and provides type deduction. auto mvar = new Foo ; // Foo mvar ; auto cvar = new const Foo ; // const (Foo) cvar ; auto ivar = new invariant Foo ; // invariant(Foo) ivar ; final fvar = new const Foo ; // final const (Foo) fvar ; -- Chris Nicholson-Sauls
I would prefer something like that. I still can't get over the feeling anytime I type or see "cast" that I'm doing something dangerous and subversive. Although I know things like cast(ClassType) in D are actually safe casts... but even using safe casts like that is kind of a warning sign in OO code that you may have factored your interface incorrectly. --bb
Jun 19 2007
parent Tristam MacDonald <swiftcoder gmail.com> writes:
Bill Baxter Wrote:
 I would prefer something like that.  I still can't get over the feeling 
 anytime I type or see "cast" that I'm doing something dangerous and 
 subversive.  Although I know things like cast(ClassType) in D are 
 actually safe casts... but even using safe casts like that is kind of a 
 warning sign in OO code that you may have factored your interface 
 incorrectly.
 
 --bb
I wouldn't say cast(const) was a OO problem - and the syntax is definitely improved over C++'s const_cast<ClassName>(), but it does point to 'C++ like' problems with how const works. I always thought the theory was that const_cast was there for dealing with legacy API's, not to overcome shortcomings in the language :)
Jun 20 2007
prev sibling parent janderson <askme me.com> writes:
Craig Black wrote:
 OK, I think I'm starting to grasp the subtle differences between const, 
 final, and invariant.  It seems to me that to have three keywords is 
 unnecessary.  Perhaps const and final could be merged into one?
 
 From my understanding, the only difference between const and final is that 
 local final fields can be initialized in a constructor, right?  Couldn't 
 that just be the default behavior of a local const field?  Then we could get 
 rid of final and have only two keywords.  Or am I missing something?  IMO, 
 two keywords is way less confusing than three.
 
 Another question.  Since invariant data should always be invariant, does it 
 make sense to be able to cast non-invariant data to invariant?  The compiler 
 will think that it is invariant when it isn't.
 
 -Craig 
 
 
I hate to be the meanie here but this newsgroup this is the sort of message I think belongs in digitalmars.D. -Joel
Jun 21 2007