www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - const by default.

reply Dave <Dave_member pathlink.com> writes:
Ok, I know 'const' has been beaten to death in previous threads...

However, one thing that I've not seen beaten to death is 'const by default'.

In the following post, there's a link to comp.lang.c++.moderated where 
Walter puts forward some very good arguments regarding what's wrong with 
C++ (type modifier) const:

http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39437

In that thread, Walter mentions that he should have made const the 
default. Every subsequent post agreed with not one dissenter.

Walter, what exactly do you have in mind? Only reference types? Default 
const for everything? Everything but function local variables? Or 
function return types and function parameters only?

If some type of 'const by default' was implemented, it could have big 
consequences for Phobos. As Phobos is 'officially' supported and 
distributed w/ the compiler, it is the only thing that has to be changed 
along with the compiler.

I'd say:
- add the 'mutable' keyword in v0.163
- let the community start modifying Phobos.
- add a "warn on non-mutable" switch to the compiler by v0.167 (that way 
Walter could implement all of the logic, and later cutover by removing 
the switch and making those errors instead of warnings).
- let the community test Phobos using the new warning switch
- 'cutover' when Phobos is done.

I think the "too much water under the bridge" problem from Walter's 
standpoint is that he can't count on anyone else but himself making the 
changes to Phobos, and he simply doesn't have the time.

I would gladly volunteer for a few of the Phobos modules but I don't 
have the time nor enough explicit knowledge of Phobos to lead the effort 
efficiently. If we could just get the 'mutable' keyword in there, then 
we could start a Dsource project and get "promises" from people in the 
community to do the work.

Just some thoughts on the matter...

Thanks,

- Dave
Jul 02 2006
next sibling parent John Reimer <terminal.node gmail.com> writes:
Dave wrote:
 Ok, I know 'const' has been beaten to death in previous threads...
 
 However, one thing that I've not seen beaten to death is 'const by 
 default'.
 
 In the following post, there's a link to comp.lang.c++.moderated where 
 Walter puts forward some very good arguments regarding what's wrong with 
 C++ (type modifier) const:
 
 http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39437
 
 In that thread, Walter mentions that he should have made const the 
 default. Every subsequent post agreed with not one dissenter.
 
 Walter, what exactly do you have in mind? Only reference types? Default 
 const for everything? Everything but function local variables? Or 
 function return types and function parameters only?
 
 If some type of 'const by default' was implemented, it could have big 
 consequences for Phobos. As Phobos is 'officially' supported and 
 distributed w/ the compiler, it is the only thing that has to be changed 
 along with the compiler.
 
 I'd say:
 - add the 'mutable' keyword in v0.163
 - let the community start modifying Phobos.
 - add a "warn on non-mutable" switch to the compiler by v0.167 (that way 
 Walter could implement all of the logic, and later cutover by removing 
 the switch and making those errors instead of warnings).
 - let the community test Phobos using the new warning switch
 - 'cutover' when Phobos is done.
 
 I think the "too much water under the bridge" problem from Walter's 
 standpoint is that he can't count on anyone else but himself making the 
 changes to Phobos, and he simply doesn't have the time.
 
 I would gladly volunteer for a few of the Phobos modules but I don't 
 have the time nor enough explicit knowledge of Phobos to lead the effort 
 efficiently. If we could just get the 'mutable' keyword in there, then 
 we could start a Dsource project and get "promises" from people in the 
 community to do the work.
 
 Just some thoughts on the matter...
 
 Thanks,
 
 - Dave
Good points! Sorry for the minimal post, but there's just not much to add to what Dave says here. -JJR
Jul 02 2006
prev sibling next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Ahem.
Excuse me, I'm not very enlightened about this "const" issue, but if 
your suggestion implies that people like me who don't care about "const" 
will have to add "mutable" qualifiers all over the place, then I'm gonna 
have to side against this, with a big NO.

If I've just said something that's too stupid, then please enlighten me. 
Thanks.

Dave wrote:
 Ok, I know 'const' has been beaten to death in previous threads...
 
 However, one thing that I've not seen beaten to death is 'const by 
 default'.
 
 In the following post, there's a link to comp.lang.c++.moderated where 
 Walter puts forward some very good arguments regarding what's wrong with 
 C++ (type modifier) const:
 
 http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39437
 
 In that thread, Walter mentions that he should have made const the 
 default. Every subsequent post agreed with not one dissenter.
 
 Walter, what exactly do you have in mind? Only reference types? Default 
 const for everything? Everything but function local variables? Or 
 function return types and function parameters only?
 
 If some type of 'const by default' was implemented, it could have big 
 consequences for Phobos. As Phobos is 'officially' supported and 
 distributed w/ the compiler, it is the only thing that has to be changed 
 along with the compiler.
 
 I'd say:
 - add the 'mutable' keyword in v0.163
 - let the community start modifying Phobos.
 - add a "warn on non-mutable" switch to the compiler by v0.167 (that way 
 Walter could implement all of the logic, and later cutover by removing 
 the switch and making those errors instead of warnings).
 - let the community test Phobos using the new warning switch
 - 'cutover' when Phobos is done.
 
 I think the "too much water under the bridge" problem from Walter's 
 standpoint is that he can't count on anyone else but himself making the 
 changes to Phobos, and he simply doesn't have the time.
 
 I would gladly volunteer for a few of the Phobos modules but I don't 
 have the time nor enough explicit knowledge of Phobos to lead the effort 
 efficiently. If we could just get the 'mutable' keyword in there, then 
 we could start a Dsource project and get "promises" from people in the 
 community to do the work.
 
 Just some thoughts on the matter...
 
 Thanks,
 
 - Dave
Jul 03 2006
parent reply BCS <BCS pathlink.com> writes:
Hasan Aljudy wrote:
 Ahem.
 Excuse me, I'm not very enlightened about this "const" issue, but if 
 your suggestion implies that people like me who don't care about "const" 
 will have to add "mutable" qualifiers all over the place, then I'm gonna 
 have to side against this, with a big NO.
 
 If I've just said something that's too stupid, then please enlighten me. 
 Thanks.
 
I'm not sure what is being suggested but it's something like this: Given a function that takes a reference type as an argument. The stuff the reference points to is not a valid target for a write unless you say so. void fn1(char[] c) { char i = c[5]; // allowed c[4] = i; // not allowed } void fn2(mutable char[] c) { char i = c[5]; // allowed c[4] = i; // allowed } Furthermore, unless a variable is mutable, you can't pass it off to a function in a mutable parameter void fn3(char[] c) { fn1(c); // allowed fn2(c); // not allowed: c is immutable } The issue as to the mutability of local variables is another thing all together. I haven't heard any agreement on what is best here. One thought I like is local reference type variables are localy mutable. However if you are passing them to a function they become implicitly immutable unless you say otherwise. (Assume that " " is the grant mutability operator) void fn4() { char[] c; c[5] = '\0'; // allowed fn1(c); // allowed fn2(c); // not allowed: arg 1 is mutable; fn2( c) // allowed } In the general case I expect that this change will have little effect on code. In my experience, most pass by reference cases are immutable anyway. The rest should be easy to find and fix as long as DMD gives good error messages.
Jul 03 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
BCS wrote:
 
 The issue as to the mutability of local variables is another thing all 
 together. I haven't heard any agreement on what is best here. One 
 thought I like is local reference type variables are localy mutable. 
 However if you are passing them to a function they become implicitly 
 immutable unless you say otherwise.
I was thinking along the same lines. There really isn't much of an advantage to making local variables immutable. Sean
Jul 03 2006
prev sibling next sibling parent reply Rémy Mouëza <ray.jay.ay.moueza DoNtSpAm.gmail.com> writes:
In article <e8bib0$1gn1$6 digitaldaemon.com>, BCS says...
Hasan Aljudy wrote:
 Ahem.
 Excuse me, I'm not very enlightened about this "const" issue, but if 
 your suggestion implies that people like me who don't care about "const" 
 will have to add "mutable" qualifiers all over the place, then I'm gonna 
 have to side against this, with a big NO.
 
 If I've just said something that's too stupid, then please enlighten me. 
 Thanks.
I also share Hasan's point of view.
I'm not sure what is being suggested but it's something like this:

Given a function that takes a reference type as an argument. The stuff 
the reference points to is not a valid target for a write unless you say so.


void fn1(char[] c)
{
	char i = c[5];	// allowed
	c[4] = i;	// not allowed
}


void fn2(mutable char[] c)
{
	char i = c[5];	// allowed
	c[4] = i;	// allowed
}
Why couldn't we do it using the "in" keyword ?
void function2 ( in char [] c )
{
	char i = c [5];	// allowed
	c [4]  = i ;	// allowed
}
Furthermore, unless a variable is mutable, you can't pass it off to a 
function in a mutable parameter

void fn3(char[] c)
{
	fn1(c);	// allowed
	fn2(c);	// not allowed: c is immutable
}
Won't we have the same troubles than in C++ ? Mainly copying the immutable variables to mutable ones that we would pass to the function:
void fn3 ( char [] c )
{
	fn1 ( c ); // allowed
	// fn2 ( c );	// not allowed: c is immutable
       mutable typeof ( c ) d = cast ( mutable ) c.dup ; // Something like this
       fn2 ( d );
}
Makes too much copy, memory inefficient for no reason.
The issue as to the mutability of local variables is another thing all 
together. I haven't heard any agreement on what is best here. One 
thought I like is local reference type variables are localy mutable. 
However if you are passing them to a function they become implicitly 
immutable unless you say otherwise. (Assume that " " is the grant 
mutability operator)

void fn4()
{
	char[] c;

	c[5] = '\0';	// allowed

	fn1(c);		// allowed
	fn2(c);		// not allowed: arg 1 is mutable;
	fn2( c)		// allowed
}
We could use the "out" keyword instead of the at sign. That might be more readable, or understandable.
In the general case I expect that this change will have little effect on 
code. In my experience, most pass by reference cases are immutable 
anyway. The rest should be easy to find and fix as long as DMD gives 
good error messages.
I don't like the C++ const type system. It creates two parallel universes... uh, type systems : the const one and the non const one, and we turn to use ugly cast or copy tricks to fight against that space time disruption. I don't want to be stuck in a worm hole again.
Jul 03 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
Rémy Mouëza wrote:
 Why couldn't we do it using the "in" keyword ?
It may or may not be ideal with respect to reference types (ie. classes) where 'inout' allows one to reassign the reference itself in addition to potentially mutating the referenced data. I'm not certain whether this distinction is worth preserving or not. Sean
Jul 03 2006
prev sibling parent BCS <BCS_member pathlink.com> writes:
In article <e8bv9b$2gu8$1 digitaldaemon.com>, Rémy Mouëza says...

[...]
Why couldn't we do it using the "in" keyword ?
"in" allows the function to change the array in the calling function. As used now, it has no barring on changeling the *contents* of said array. [...]
Won't we have the same troubles than in C++ ? Mainly copying the immutable
variables to mutable ones that we would pass to the function: 
What else could you do? Assume a reference to immutable data, and a function that takes a mutable reference. If the idea of "const" is going to have an meaning at all, you can't pass the reference to the function because the mutable attribute as much as says "I'll going to change this data". Unless I'm missing something huge, you have to pass the function a copy or not use the function. [...]
We could use the "out" keyword instead of the at sign. That might be more
readable, or understandable.
The syntax is almost irrelevant at this point, however "out" don't seem to intuitive to me. OTOH I can't think of any better keywords at this point. All in all, I haven't made up my mind on how to do const. Const by default looks viable at this point.
Jul 04 2006
prev sibling next sibling parent Joseph M Link <joelink joelink.net> writes:
BCS wrote:
 Hasan Aljudy wrote:
 Ahem.
 Excuse me, I'm not very enlightened about this "const" issue, but if 
 your suggestion implies that people like me who don't care about 
 "const" will have to add "mutable" qualifiers all over the place, then 
 I'm gonna have to side against this, with a big NO.

 If I've just said something that's too stupid, then please enlighten 
 me. Thanks.
I'm not sure what is being suggested but it's something like this: Given a function that takes a reference type as an argument. The stuff the reference points to is not a valid target for a write unless you say so. void fn1(char[] c) { char i = c[5]; // allowed c[4] = i; // not allowed } void fn2(mutable char[] c) { char i = c[5]; // allowed c[4] = i; // allowed } Furthermore, unless a variable is mutable, you can't pass it off to a function in a mutable parameter void fn3(char[] c) { fn1(c); // allowed fn2(c); // not allowed: c is immutable } The issue as to the mutability of local variables is another thing all together. I haven't heard any agreement on what is best here. One thought I like is local reference type variables are localy mutable. However if you are passing them to a function they become implicitly immutable unless you say otherwise. (Assume that " " is the grant mutability operator) void fn4() { char[] c; c[5] = '\0'; // allowed fn1(c); // allowed fn2(c); // not allowed: arg 1 is mutable; fn2( c) // allowed } In the general case I expect that this change will have little effect on code. In my experience, most pass by reference cases are immutable anyway. The rest should be easy to find and fix as long as DMD gives good error messages.
I would also propose that mutable function parameters become locally mutable in the scope of the function. This would make it necessary to always 'grant mutability' and those make it obvious when reading code. ie: void fn5(char[] b, mutable char[] d) { char[] c; b[5] = '\0'; // not allowed: b is immutable c[5] = '\0'; // allowed d[5] = '\0'; // allowed fn1(b); // allowed fn1(c); // allowed fn1(d); // allowed fn2(b); // not allowed: arg 1 is mutable; fn2(c); // not allowed: arg 1 is mutable; fn2(d); // not allowed: arg 1 is mutable; fn2( b) // not allowed: b is immutable fn2( c) // allowed fn2( d) // allowed } Joe
Jul 04 2006
prev sibling parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
BCS wrote:
 However if you are passing them to a function they become implicitly
 immutable unless you say otherwise. (Assume that " " is the grant
 mutability operator)
 
 void fn4()
 {
     char[] c;
 
     c[5] = '\0';    // allowed
 
     fn1(c);        // allowed
     fn2(c);        // not allowed: arg 1 is mutable;
     fn2( c)        // allowed
 }
 
 In the general case I expect that this change will have little effect on
 code. In my experience, most pass by reference cases are immutable
 anyway. The rest should be easy to find and fix as long as DMD gives
 good error messages.
I think there's a problem with all this "grant mutability/immutability", which is that we're just degenerating into C++ with its const_cast. With it, the compiler has few, if any, guarantees about the constness of anything --- it can always be casted away. The way I see it, something either is or isn't mutable, and it should stay that way for the duration of the program --- in some cases, for the duration of a function or the lifetime of an object.
Jul 04 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
Deewiant wrote:
 BCS wrote:
 However if you are passing them to a function they become implicitly
 immutable unless you say otherwise. (Assume that " " is the grant
 mutability operator)

 void fn4()
 {
     char[] c;

     c[5] = '\0';    // allowed

     fn1(c);        // allowed
     fn2(c);        // not allowed: arg 1 is mutable;
     fn2( c)        // allowed
 }

 In the general case I expect that this change will have little effect on
 code. In my experience, most pass by reference cases are immutable
 anyway. The rest should be easy to find and fix as long as DMD gives
 good error messages.
I think there's a problem with all this "grant mutability/immutability", which is that we're just degenerating into C++ with its const_cast. With it, the compiler has few, if any, guarantees about the constness of anything --- it can always be casted away. The way I see it, something either is or isn't mutable, and it should stay that way for the duration of the program --- in some cases, for the duration of a function or the lifetime of an object.
I think the issue is to find a balance between clarity and elegance. On the surface, const as default would suggest the need to qualify nearly all local variables as 'mutable'. But if the issue really is enforcing call contracts for function parameters and return values, as well as loop invariant optimization, then perhaps const-ness could be limited to these areas as well? For example, it should only be necessary to qualify reference types as 'mutable' as everything else is passed by value anyway. I am coming to think that 'in' vs. 'inout' may be sufficient to distinguish intent for function parameters, which leaves return values and declarations. I can't say I'm entirely happy with the idea of using 'mutable' all over the place for declarations even though it would probably be easiest. In some respects I'd rather leave declarations as-is and "mutable" qualify variables at the point of use: MyClass fn( MyClass c, inout MyClass d ) {} MyClass a, b; inout MyClass e = fn( a, inout b ); // error But I'll admit to not being entirely happy with this syntax either. Sean
Jul 04 2006
prev sibling parent reply BCS <BCS pathlink.com> writes:
Deewiant wrote:
 
 
 I think there's a problem with all this "grant mutability/immutability", which
 is that we're just degenerating into C++ with its const_cast. With it, the
 compiler has few, if any, guarantees about the constness of anything --- it can
 always be casted away.
Casting away mutability (unless I'm totally nuts) is always safe. Casting away immutability should never be allowed.
 
 The way I see it, something either is or isn't mutable, and it should stay that
 way for the duration of the program --- in some cases, for the duration of a
 function or the lifetime of an object.
Each specific reference *would* be mutable or immutable for it's entire duration. It would be a compile time attribute of a reference. The only time that the mutability of a reference would change is when it is copied to another reference, in a function call for instance, and then the only change that can be made is the new reference can *lose* mutability.
Jul 05 2006
parent reply Sean Kelly <sean f4.ca> writes:
BCS wrote:
 Deewiant wrote:
 I think there's a problem with all this "grant 
 mutability/immutability", which
 is that we're just degenerating into C++ with its const_cast. With it, 
 the
 compiler has few, if any, guarantees about the constness of anything 
 --- it can
 always be casted away.
Casting away mutability (unless I'm totally nuts) is always safe. Casting away immutability should never be allowed.
Exactly. This is much of the reason for the "const as default" idea, as it makes sense to convert something to a more general representation (in this case mutable to immutable) but not vice-versa. C++ got this backwards by making mutable the general category. Sean
Jul 05 2006
parent Don Clugston <dac nospam.com.au> writes:
Sean Kelly wrote:
 BCS wrote:
 Deewiant wrote:
 I think there's a problem with all this "grant 
 mutability/immutability", which
 is that we're just degenerating into C++ with its const_cast. With 
 it, the
 compiler has few, if any, guarantees about the constness of anything 
 --- it can
 always be casted away.
Casting away mutability (unless I'm totally nuts) is always safe. Casting away immutability should never be allowed.
Exactly. This is much of the reason for the "const as default" idea, as it makes sense to convert something to a more general representation (in this case mutable to immutable) but not vice-versa. C++ got this backwards by making mutable the general category.
And then had to add the 'mutable' keyword anyway <g>.
Jul 05 2006
prev sibling next sibling parent reply clayasaurus <clayasaurus gmail.com> writes:
Dave wrote:
 Ok, I know 'const' has been beaten to death in previous threads...
 
 However, one thing that I've not seen beaten to death is 'const by 
 default'.
 
 In the following post, there's a link to comp.lang.c++.moderated where 
 Walter puts forward some very good arguments regarding what's wrong with 
 C++ (type modifier) const:
 
 http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39437
 
 In that thread, Walter mentions that he should have made const the 
 default. Every subsequent post agreed with not one dissenter.
 
 Walter, what exactly do you have in mind? Only reference types? Default 
 const for everything? Everything but function local variables? Or 
 function return types and function parameters only?
 
 If some type of 'const by default' was implemented, it could have big 
 consequences for Phobos. As Phobos is 'officially' supported and 
 distributed w/ the compiler, it is the only thing that has to be changed 
 along with the compiler.
 
 I'd say:
 - add the 'mutable' keyword in v0.163
 - let the community start modifying Phobos.
 - add a "warn on non-mutable" switch to the compiler by v0.167 (that way 
 Walter could implement all of the logic, and later cutover by removing 
 the switch and making those errors instead of warnings).
 - let the community test Phobos using the new warning switch
 - 'cutover' when Phobos is done.
 
 I think the "too much water under the bridge" problem from Walter's 
 standpoint is that he can't count on anyone else but himself making the 
 changes to Phobos, and he simply doesn't have the time.
 
 I would gladly volunteer for a few of the Phobos modules but I don't 
 have the time nor enough explicit knowledge of Phobos to lead the effort 
 efficiently. If we could just get the 'mutable' keyword in there, then 
 we could start a Dsource project and get "promises" from people in the 
 community to do the work.
 
 Just some thoughts on the matter...
 
 Thanks,
 
 - Dave
I wasn't necessarily supporting it, but if all the D experts think it is a good idea after having a long conversation about it in the newsgroups, then I wouldn't mind making changes.
Jul 03 2006
parent David Medlock <noone nowhere.com> writes:
clayasaurus wrote:

 Dave wrote:
 
 Ok, I know 'const' has been beaten to death in previous threads...

 However, one thing that I've not seen beaten to death is 'const by 
 default'.

 In the following post, there's a link to comp.lang.c++.moderated where 
 Walter puts forward some very good arguments regarding what's wrong 
 with C++ (type modifier) const:

 http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39437

 In that thread, Walter mentions that he should have made const the 
 default. Every subsequent post agreed with not one dissenter.

 Walter, what exactly do you have in mind? Only reference types? 
 Default const for everything? Everything but function local variables? 
 Or function return types and function parameters only?

 If some type of 'const by default' was implemented, it could have big 
 consequences for Phobos. As Phobos is 'officially' supported and 
 distributed w/ the compiler, it is the only thing that has to be 
 changed along with the compiler.

 I'd say:
 - add the 'mutable' keyword in v0.163
 - let the community start modifying Phobos.
 - add a "warn on non-mutable" switch to the compiler by v0.167 (that 
 way Walter could implement all of the logic, and later cutover by 
 removing the switch and making those errors instead of warnings).
 - let the community test Phobos using the new warning switch
 - 'cutover' when Phobos is done.

 I think the "too much water under the bridge" problem from Walter's 
 standpoint is that he can't count on anyone else but himself making 
 the changes to Phobos, and he simply doesn't have the time.

 I would gladly volunteer for a few of the Phobos modules but I don't 
 have the time nor enough explicit knowledge of Phobos to lead the 
 effort efficiently. If we could just get the 'mutable' keyword in 
 there, then we could start a Dsource project and get "promises" from 
 people in the community to do the work.

 Just some thoughts on the matter...

 Thanks,

 - Dave
I wasn't necessarily supporting it, but if all the D experts think it is a good idea after having a long conversation about it in the newsgroups, then I wouldn't mind making changes.
FYI: I posted my thoughts in D.learn under : "so what exactly is const supposed to mean?" I should have posted here...oh well.
Jul 03 2006
prev sibling next sibling parent reply Chad J <gamerChad _spamIsBad_gmail.com> writes:
So far I'm pretty convinced that some kind of "constness" is a good 
thing.  I've already run into one area where this would be useful.

I have one peeve about it though: I really would not like it if the 
keyword used to represent constness was "const".  I will explain from my 
newbie-to-Cplusplus background, having come from languages that seem, at 
least to me, to be much more well thought out than Cplusplus.

When I see "const" I think of it as a shorthand for "constant", just as 
"bool" is shorthand for "boolean".  My understanding of something 
constant is that it does not change... EVER.  Thus it makes no sense to 
me why something as ephemeral as data passed into a function could be 
considered constant.  If the constant data leaves the scope of the 
function, becomes no longer constant, and gets changed, then it isn't 
really constant to me.

I do like the mutable word though, as it seems to have an english 
meaning very close to its programming meaning  :)
It also seems that if we were to make things immutable by default, we 
could make an "immutable" keyword.  Sure it's kinda long, but since most 
things are that by default then we won't be typing it much.  It also 
seems so much more logically related to the word "mutable".

Another worry I have is that of being stuck with many instances of 
"mutable" littering my code, if only because said code happens to modify 
referenced data a lot.  One way I might see this worry dissappearing if 
there was a way to blanket stuff into being immutable, in order to avoid 
repeating the word over and over again.  Sorta like:

class Foo
{
   mutable:
     int[] data; // this is mutable
     char[] name; // this too
     // etc
}

or maybe even something as radical as

mutable
{
   // from now on everything works as it used to

   void func1( char[] string1, char[] string2 )
   {
     string1[5] = 'a'; // ok
     string2[3] = 'b'; // also good
   }

   void func2( int[] data )
   {
     data[8] = 42; // just dandy.
   }
}

Note:  I am probably so newbish at language design compared to you guys 
it is not even funny, so maybe the syntax suggestions suck, but please 
consider my naming plea, at least as a "this experience was unpleasant 
so please fix it" sorta thing.
Jul 03 2006
parent reply kris <foo bar.com> writes:
Chad J wrote:
 So far I'm pretty convinced that some kind of "constness" is a good 
 thing.  I've already run into one area where this would be useful.
 
 I have one peeve about it though: I really would not like it if the 
 keyword used to represent constness was "const".  I will explain from my 
 newbie-to-Cplusplus background, having come from languages that seem, at 
 least to me, to be much more well thought out than Cplusplus.
 
 When I see "const" I think of it as a shorthand for "constant", just as 
 "bool" is shorthand for "boolean".  My understanding of something 
 constant is that it does not change... EVER.  Thus it makes no sense to 
 me why something as ephemeral as data passed into a function could be 
 considered constant.  If the constant data leaves the scope of the 
 function, becomes no longer constant, and gets changed, then it isn't 
 really constant to me.
 
 I do like the mutable word though, as it seems to have an english 
 meaning very close to its programming meaning  :)
 It also seems that if we were to make things immutable by default, we 
 could make an "immutable" keyword.  Sure it's kinda long, but since most 
 things are that by default then we won't be typing it much.  It also 
 seems so much more logically related to the word "mutable".
 
 Another worry I have is that of being stuck with many instances of 
 "mutable" littering my code, if only because said code happens to modify 
 referenced data a lot.  One way I might see this worry dissappearing if 
 there was a way to blanket stuff into being immutable, in order to avoid 
 repeating the word over and over again.  Sorta like:
 
 class Foo
 {
   mutable:
     int[] data; // this is mutable
     char[] name; // this too
     // etc
 }
 
 or maybe even something as radical as
 
 mutable
 {
   // from now on everything works as it used to
 
   void func1( char[] string1, char[] string2 )
   {
     string1[5] = 'a'; // ok
     string2[3] = 'b'; // also good
   }
 
   void func2( int[] data )
   {
     data[8] = 42; // just dandy.
   }
 }
 
 Note:  I am probably so newbish at language design compared to you guys 
 it is not even funny, so maybe the syntax suggestions suck, but please 
 consider my naming plea, at least as a "this experience was unpleasant 
 so please fix it" sorta thing.
hehe -- that would certainly resolve the problem for existing libraries: just wrap each entire module in a mutable{} block -- phobos would be done in 15 minutes :D Good idea!
Jul 03 2006
next sibling parent reply "Boris Wang" <nano.kago hotmail.com> writes:
"kris" <foo bar.com> ??????:e8cu1q$nbc$1 digitaldaemon.com...
 Chad J wrote:
 So far I'm pretty convinced that some kind of "constness" is a good 
 thing.  I've already run into one area where this would be useful.

 I have one peeve about it though: I really would not like it if the 
 keyword used to represent constness was "const".  I will explain from my 
 newbie-to-Cplusplus background, having come from languages that seem, at 
 least to me, to be much more well thought out than Cplusplus.

 When I see "const" I think of it as a shorthand for "constant", just as 
 "bool" is shorthand for "boolean".  My understanding of something 
 constant is that it does not change... EVER.  Thus it makes no sense to 
 me why something as ephemeral as data passed into a function could be 
 considered constant.  If the constant data leaves the scope of the 
 function, becomes no longer constant, and gets changed, then it isn't 
 really constant to me.

 I do like the mutable word though, as it seems to have an english meaning 
 very close to its programming meaning  :)
 It also seems that if we were to make things immutable by default, we 
 could make an "immutable" keyword.  Sure it's kinda long, but since most 
 things are that by default then we won't be typing it much.  It also 
 seems so much more logically related to the word "mutable".

 Another worry I have is that of being stuck with many instances of 
 "mutable" littering my code, if only because said code happens to modify 
 referenced data a lot.  One way I might see this worry dissappearing if 
 there was a way to blanket stuff into being immutable, in order to avoid 
 repeating the word over and over again.  Sorta like:

 class Foo
 {
   mutable:
     int[] data; // this is mutable
     char[] name; // this too
     // etc
 }

 or maybe even something as radical as

 mutable
 {
   // from now on everything works as it used to

   void func1( char[] string1, char[] string2 )
   {
     string1[5] = 'a'; // ok
     string2[3] = 'b'; // also good
   }

   void func2( int[] data )
   {
     data[8] = 42; // just dandy.
   }
 }

 Note:  I am probably so newbish at language design compared to you guys 
 it is not even funny, so maybe the syntax suggestions suck, but please 
 consider my naming plea, at least as a "this experience was unpleasant so 
 please fix it" sorta thing.
hehe -- that would certainly resolve the problem for existing libraries: just wrap each entire module in a mutable{} block -- phobos would be done in 15 minutes :D Good idea!
NO, Yet another colon / brace syntax.
Jul 03 2006
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Tue, 4 Jul 2006 13:42:11 +0800, Boris Wang wrote:

 "kris" <foo bar.com> ??????:e8cu1q$nbc$1 digitaldaemon.com...
 Chad J wrote:
 So far I'm pretty convinced that some kind of "constness" is a good 
 thing.  I've already run into one area where this would be useful.

 I have one peeve about it though: I really would not like it if the 
 keyword used to represent constness was "const".  I will explain from my 
 newbie-to-Cplusplus background, having come from languages that seem, at 
 least to me, to be much more well thought out than Cplusplus.

 When I see "const" I think of it as a shorthand for "constant", just as 
 "bool" is shorthand for "boolean".  My understanding of something 
 constant is that it does not change... EVER.  Thus it makes no sense to 
 me why something as ephemeral as data passed into a function could be 
 considered constant.  If the constant data leaves the scope of the 
 function, becomes no longer constant, and gets changed, then it isn't 
 really constant to me.

 I do like the mutable word though, as it seems to have an english meaning 
 very close to its programming meaning  :)
 It also seems that if we were to make things immutable by default, we 
 could make an "immutable" keyword.  Sure it's kinda long, but since most 
 things are that by default then we won't be typing it much.  It also 
 seems so much more logically related to the word "mutable".

 Another worry I have is that of being stuck with many instances of 
 "mutable" littering my code, if only because said code happens to modify 
 referenced data a lot.  One way I might see this worry dissappearing if 
 there was a way to blanket stuff into being immutable, in order to avoid 
 repeating the word over and over again.  Sorta like:

 class Foo
 {
   mutable:
     int[] data; // this is mutable
     char[] name; // this too
     // etc
 }

 or maybe even something as radical as

 mutable
 {
   // from now on everything works as it used to

   void func1( char[] string1, char[] string2 )
   {
     string1[5] = 'a'; // ok
     string2[3] = 'b'; // also good
   }

   void func2( int[] data )
   {
     data[8] = 42; // just dandy.
   }
 }

 Note:  I am probably so newbish at language design compared to you guys 
 it is not even funny, so maybe the syntax suggestions suck, but please 
 consider my naming plea, at least as a "this experience was unpleasant so 
 please fix it" sorta thing.
hehe -- that would certainly resolve the problem for existing libraries: just wrap each entire module in a mutable{} block -- phobos would be done in 15 minutes :D Good idea!
NO, Yet another colon / brace syntax.
Disregard Boris ;-) It's a great idea. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 4/07/2006 3:48:13 PM
Jul 03 2006
parent "Boris Wang" <nano.kago hotmail.com> writes:
"Derek Parnell" <derek nomail.afraid.org> 
??????:zrz58urdcgmf$.yw3ohvtn0rct$.dlg 40tude.net...
 On Tue, 4 Jul 2006 13:42:11 +0800, Boris Wang wrote:

 "kris" <foo bar.com> ??????:e8cu1q$nbc$1 digitaldaemon.com...
 Chad J wrote:
 So far I'm pretty convinced that some kind of "constness" is a good
 thing.  I've already run into one area where this would be useful.

 I have one peeve about it though: I really would not like it if the
 keyword used to represent constness was "const".  I will explain from 
 my
 newbie-to-Cplusplus background, having come from languages that seem, 
 at
 least to me, to be much more well thought out than Cplusplus.

 When I see "const" I think of it as a shorthand for "constant", just as
 "bool" is shorthand for "boolean".  My understanding of something
 constant is that it does not change... EVER.  Thus it makes no sense to
 me why something as ephemeral as data passed into a function could be
 considered constant.  If the constant data leaves the scope of the
 function, becomes no longer constant, and gets changed, then it isn't
 really constant to me.

 I do like the mutable word though, as it seems to have an english 
 meaning
 very close to its programming meaning  :)
 It also seems that if we were to make things immutable by default, we
 could make an "immutable" keyword.  Sure it's kinda long, but since 
 most
 things are that by default then we won't be typing it much.  It also
 seems so much more logically related to the word "mutable".

 Another worry I have is that of being stuck with many instances of
 "mutable" littering my code, if only because said code happens to 
 modify
 referenced data a lot.  One way I might see this worry dissappearing if
 there was a way to blanket stuff into being immutable, in order to 
 avoid
 repeating the word over and over again.  Sorta like:

 class Foo
 {
   mutable:
     int[] data; // this is mutable
     char[] name; // this too
     // etc
 }

 or maybe even something as radical as

 mutable
 {
   // from now on everything works as it used to

   void func1( char[] string1, char[] string2 )
   {
     string1[5] = 'a'; // ok
     string2[3] = 'b'; // also good
   }

   void func2( int[] data )
   {
     data[8] = 42; // just dandy.
   }
 }

 Note:  I am probably so newbish at language design compared to you guys
 it is not even funny, so maybe the syntax suggestions suck, but please
 consider my naming plea, at least as a "this experience was unpleasant 
 so
 please fix it" sorta thing.
hehe -- that would certainly resolve the problem for existing libraries: just wrap each entire module in a mutable{} block -- phobos would be done in 15 minutes :D Good idea!
NO, Yet another colon / brace syntax.
Disregard Boris ;-) It's a great idea.
Please disregard me, again, :) I work at linux kernel about two years once, love reading the kernel mail list. i learn about what's seriousness, professional and hacker in there. until now, my whole works not on windows os. IMHO, in NG of D, i can't get the feelings got from linux kernel mail list. The idea, like above, can't be approved in the world of LK.
 -- 
 Derek
 (skype: derek.j.parnell)
 Melbourne, Australia
 "Down with mediocrity!"
 4/07/2006 3:48:13 PM
 
Jul 04 2006
prev sibling parent John Reimer <terminal.node gmail.com> writes:
kris wrote:

 
 hehe -- that would certainly resolve the problem for existing libraries: 
 just wrap each entire module in a mutable{} block -- phobos would be 
 done in 15 minutes :D
 
 Good idea!
lol!
Jul 03 2006
prev sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Const has a number of issues whether or not it is default:

1) function parameters that are reference types (what is talked about 
most here) being const
2) member functions being able to modify the object instance (const 
functions)
3) const in the return value
4) what happens if both const and non-const references to the same data 
are simultaneous, and one modifies through the non-const one?
5) assignment of a const reference to a non-const one, either explicitly 
or through a function parameter
6) what happens if one returns a const reference

One way to do it is to have const-as-type-modifier like C++, something 
I've tried to avoid as being excessively complex (compiler and 
programmer) and ugly.

Another way I've been toying with is just making the 'in' parameter 
storage class imply const reference:

class C { int m; }

void bar(C c) { c.m = 3; } // ok

void foo(in C c) { c.m = 3; } // error

void foo(in C c) { c = new C(); } // ok

C foo(in C c) { return c; } // ok

void foo(in C c) { bar(c); } // ok

void foo(in C c)
{   C d = c;
     d.m = 3;  // ok
}

What it provides is the most asked for characteristic of const.
Jul 07 2006
next sibling parent reply kris <foo bar.com> writes:
Walter Bright wrote:
 Const has a number of issues whether or not it is default:
 
 1) function parameters that are reference types (what is talked about 
 most here) being const
 2) member functions being able to modify the object instance (const 
 functions)
 3) const in the return value
 4) what happens if both const and non-const references to the same data 
 are simultaneous, and one modifies through the non-const one?
 5) assignment of a const reference to a non-const one, either explicitly 
 or through a function parameter
 6) what happens if one returns a const reference
 
 One way to do it is to have const-as-type-modifier like C++, something 
 I've tried to avoid as being excessively complex (compiler and 
 programmer) and ugly.
 
 Another way I've been toying with is just making the 'in' parameter 
 storage class imply const reference:
 
 class C { int m; }
 
 void bar(C c) { c.m = 3; } // ok
 
 void foo(in C c) { c.m = 3; } // error
 
 void foo(in C c) { c = new C(); } // ok
 
 C foo(in C c) { return c; } // ok
 
 void foo(in C c) { bar(c); } // ok
 
 void foo(in C c)
 {   C d = c;
     d.m = 3;  // ok
 }
 
 What it provides is the most asked for characteristic of const.
Er, that's great, but does it provide for const return-values? You see, the above can be handled adequately via either struct or class /right now/ ~ but their immutablity can quickly unravel when, for example, exposing content via toString() or whatever. And please don't suggest returning a .dup of the content instead.
Jul 07 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
kris wrote:
 Er, that's great, but does it provide for const return-values?
No, it does not.
 You see, 
 the above can be handled adequately via either struct or class /right 
 now/ ~ but their immutablity can quickly unravel when, for example, 
 exposing content via toString() or whatever. And please don't suggest 
 returning a .dup of the content instead.
I've argued against the .dup method many times <g>.
Jul 07 2006
parent kris <foo bar.com> writes:
Walter Bright wrote:
 kris wrote:
 
 Er, that's great, but does it provide for const return-values?
No, it does not.
Well, that's what's actually needed to tighten up the contractual agreement between callee and caller. The 'inbound' cases /could/ be handled purely via aggregates, given an immutable return-type. As such, the latter would appear to be the base case. It would be nice to see the 'in' support, but it won't add any additional strength to the language.
 
 You see, the above can be handled adequately via either struct or 
 class /right now/ ~ but their immutablity can quickly unravel when, 
 for example, exposing content via toString() or whatever. And please 
 don't suggest returning a .dup of the content instead.
I've argued against the .dup method many times <g>.
Just a friendly reminder <g>
Jul 07 2006
prev sibling next sibling parent reply BCS <BCS pathlink.com> writes:
Walter Bright wrote:
[...]
 class C { int m; }
 void bar(C c) { c.m = 3; } // ok
[...]
 
 C foo(in C c) { return c; } // ok
 
 void foo(in C c) { bar(c); } // ok
 
 void foo(in C c)
 {   C d = c;
     d.m = 3;  // ok
 }
 
How would the last three work? IIRC, const implies that data is not accessible for writes. In the first of those three, the return value has no indication of const'ness so something like this could be done void bad(in C c) { c.m = 0; //error foo(c).m = 0; //same effect, but OK } The next one has the same effect, bar changes the parameter, where as the calling function isn't allowed to. The last one again lets a function change something it shouldn't. I feel like I'm missing something here, these seem to obvious for you to have missed. Maybe I'm looking for something other than what you are trying for. What I want is a way to get an assurance by the compiler that a referenced value will not be changed. This would require that const references (or a non mutable ones) can never be made into a mutable references. If I'm missing something, please point it out.
Jul 07 2006
next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
BCS wrote:
 Walter Bright wrote:
 [...]
  > class C { int m; }
  > void bar(C c) { c.m = 3; } // ok
 [...]
 C foo(in C c) { return c; } // ok

 void foo(in C c) { bar(c); } // ok

 void foo(in C c)
 {   C d = c;
     d.m = 3;  // ok
 }
How would the last three work?
The compiler would accept them, though I'd say it would be a bad programming practice.
 IIRC, const implies that data is not 
 accessible for writes. In the first of those three, the return value has 
 no indication of const'ness so something like this could be done
That's right.
 What I want is a way to get an assurance by the compiler that a 
 referenced value will not be changed. This would require that const 
 references (or a non mutable ones) can never be made into a mutable 
 references.
 
 If I'm missing something, please point it out.
You haven't missed something. The 'in' thing proposed above is not an airtight guarantee, you could call it more of a 'sieve'. It's more of a documentation aid. The compiler checking would be minimal and easily subverted.
Jul 07 2006
parent BCS <BCS pathlink.com> writes:
Walter Bright wrote:
 BCS wrote:
 
 What I want is a way to get an assurance by the compiler that a 
 referenced value will not be changed. This would require that const 
 references (or a non mutable ones) can never be made into a mutable 
 references.

 If I'm missing something, please point it out.
You haven't missed something. The 'in' thing proposed above is not an airtight guarantee, you could call it more of a 'sieve'. It's more of a documentation aid. The compiler checking would be minimal and easily subverted.
Uh... Uh... Please tell me that's not going to be the Final Solution? A strong consistent const concept (IMVHO) would be a great thing for D. While the suggested use of "in" might help /some/, I don't see it being nearly as useful. For one thing (and this is just a gut reaction) it don't seem vary extensible. I fear it might be just good enough that it won't ever get replaced with something better. Frankly, because of that, I'd rather see it left as-is or go to a highly restrictive const system than havening the "in" system be the primary const concept.
Jul 07 2006
prev sibling parent kris <foo bar.com> writes:
BCS wrote:
 What I want is a way to get an assurance by the compiler that a 
 referenced value will not be changed. This would require that const 
 references (or a non mutable ones) can never be made into a mutable 
 references.
Hear hear :) Just to clarify a little on the "will not be changed" aspect: an irresponsible user can subvert pretty much language with a cast() facility; trapping irresponsible behaviour should *not* be considered as part of this request. As noted before, we're not trying to cure stupidity. Instead, we're looking for a means whereby DesignA is not /mistakenly/ subverted via pedestrian usage ~ a method in which to be more explicit about how DesignA is intended to be used, and which the compiler can accurately report upon. Various pleadings to avoid incorrect usage from within the documentation of DesignA are hardly sufficient. And CoW is missing the necessary meta-data to understand whether a dup is required or not. Thus, there's no way to contractually enforce CoW (ignoring various concerns regarding CoW inefficiency and so on)
Jul 07 2006
prev sibling next sibling parent reply Brad Roberts <braddr puremagic.com> writes:
Walter Bright wrote:
 class C { int m; }
 
 void bar(C c) { c.m = 3; } // ok
 
 void foo(in C c) { bar(c); } // ok
I have a problem with this chain.. Foo shouldn't be allowed to pass a const thing into a function that wants a mutable thing.
Jul 07 2006
next sibling parent Dave <Dave_member pathlink.com> writes:
Brad Roberts wrote:
 Walter Bright wrote:
 class C { int m; }

 void bar(C c) { c.m = 3; } // ok

 void foo(in C c) { bar(c); } // ok
I have a problem with this chain.. Foo shouldn't be allowed to pass a const thing into a function that wants a mutable thing.
I have a problem with that and this also: void foo(in C c) { C d = c; d.m = 3; // ok } If c is passed 'read-only' (meaning the intention of the parameter passed 'in' was to use the members for informational purposes inside the function only), why allow c to be assigned to a 'non-const'? If you look at 'in' as meaning "read-only / informational" then neither of these should be allowed. And if neither of these are allowed, then the programmer and compiler could both have something to count on, right? But, I guess there's still the problem of: C _c; void main() { C c = new C(); c.m = 100; _c = c; // lots of code foo(c); printf("%d\n",c.m); // now 1000 after returning from foo() } void foo(in C c) { _c.m = c.m * 10; } class C { int m; } Hmmm, would it then be feasible to do a run-time check for non-release builds like this: void foo(in C c) { /* inserted by the compiler */ assert(_c !is c,"non-local _c is a reference to an 'in' parameter"); /* inserted by the compiler */ _c.m = c.m * 10; } The same check could be used for any 'in' reference parameter (arrays, pointers, AA's). That way the programmer and compiler could both count on 'in' with the same level of confidence they do with array bounds checking now. - Dave
Jul 07 2006
prev sibling parent kris <foo bar.com> writes:
Brad Roberts wrote:
 Walter Bright wrote:
 
 class C { int m; }

 void bar(C c) { c.m = 3; } // ok

 void foo(in C c) { bar(c); } // ok
I have a problem with this chain.. Foo shouldn't be allowed to pass a const thing into a function that wants a mutable thing.
Brad ~ you might be interested in the thread over in d.learn? The premise is that, assuming readonly arrays can be supported, everything else can be made readonly via encapsulation and accessor methods. It would tend to make for a pretty simple implementation, along with simple rules? The thread is called "read only array reference", but perhaps should be called "bang for the buck" instead
Jul 07 2006
prev sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 07 Jul 2006 10:42:41 -0700, Walter Bright  
<newshound digitalmars.com> wrote:
 void bar(C c) { c.m = 3; } // ok
 void foo(in C c) { c.m = 3; } // error
I don't like that you're differentiating between implicit and explicit use of 'in'. I assume you're doing this to preserve backward compatibility with existing D code and/or to avoid having to create/add a mutable keyword? Regan
Jul 08 2006