www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Poll: Would you like to try const-by-default or not?

reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
This is not a discussion thread.  I think we've discussed enough.  :)

Basically there are these possible const implementations (there are others, 
but for the sake of simplicitly, I'll keep this poll to 2):

1) C++ style const, where you mark anything that should be const as such.

2) Parameters are const-by-default, and must be marked mutable otherwise. 
Locals, fields etc. are still mutable by default.

Walter doesn't want to stray from option 1, because 2 is basically "too 
weird."

Please reply with your choice, and maybe a small explanation of why.

I'll start this off by saying I'm definitely willing to try option 2.  I 
never really learned const-correctness in C++ because it looked so damned 
awful.  Option 2 makes more sense to me. 
Jun 10 2007
next sibling parent Johan Granberg <lijat.meREM OVEgmail.com> writes:
Jarrett Billingsley wrote:

 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are
 others, but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise.
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too
 weird."
 
 Please reply with your choice, and maybe a small explanation of why.
 
 I'll start this off by saying I'm definitely willing to try option 2.  I
 never really learned const-correctness in C++ because it looked so damned
 awful.  Option 2 makes more sense to me.

Option 2 sounds like the choice to require less typing and is safer so 2 for me.
Jun 10 2007
prev sibling next sibling parent Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
Jarrett Billingsley wrote:
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 

Option 2, because it's easier to catch bugs with it. If you forget to set something const you might accidentally modify it without meaning to. If you forget to set something mutable, the code doesn't compile. -- Remove ".doesnotlike.spam" from the mail address.
Jun 10 2007
prev sibling next sibling parent Derek Parnell <derek psych.ward> writes:
On Sun, 10 Jun 2007 10:46:40 -0400, Jarrett Billingsley wrote:

 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.

No, thank you. Not that I'm an expert but this paradigm seems to be to have been tried and found wanting.
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.

Yes, please. Let's make it harder to code accidental mistakes and easier to code safety. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
Jun 10 2007
prev sibling next sibling parent Sebastian Beschke <s.beschke gmx.de> writes:
Jarrett Billingsley schrieb:
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.

2. Since I'm not a person with a lot of code in D1, I don't mind language changes that require a lot of rewriting.
Jun 10 2007
prev sibling next sibling parent Roald Ribe <rr.nospam nospam.teikom.no> writes:
Less typing AND safer in the end? It is a no brainer. 2
Jun 10 2007
prev sibling next sibling parent Regan Heath <regan netmail.co.nz> writes:
Jarrett Billingsley Wrote:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.

I just wanted to note that "marking" in this case was the addition of 'in', not 'const' as in C++. I don't want us miss-representing the option, especially as I am going to... (continued below)
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.

vote for this one of course! Unfortunately I suspect the people with the most influence over Walter, and by this I mean people he has talked about these sorts of things for a long time, has a healthy respect for, and for good reason, are voting the other way. Which makes me sad. Regan
Jun 10 2007
prev sibling next sibling parent Mandel <mandel spam.no> writes:
I vote for 2.
It seems simple and reasonable for me.
C++ const was often a headache for me.
Constness by default also feels just right. :P
Jun 10 2007
prev sibling next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Jarrett Billingsley wrote:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too 
 weird."
 

I would really like to give option 2 a try too. I mean we have very concrete and oft-encountered reasons why #2 should be better on the one hand * better safety / documentation (because compiler won't let you forget a necessary 'mutable') * better maintainablity (because fewer users of an API will be affected by later changing a parameter to 'mutable' than to 'const') * less typing (since more paramters are const than not) and a lot of vague hand-waving on the other * "just too different" (but apparently it's ok for perl6 or euphoria) * "It'll be weird having extern C functions act differently from D ones" (they already do) * "having same type defaults is better for generics" (maybe...but I'm not convinced. If you have powerful enough metaprogramming it shouldn't be hard to strip const from a type tuple, or add it. And people do far more programming than meta-programming.) If someone could A) come up with realistic concrete examples of #2 being problematic or a severe pain to use and B) also convince me that the problematic case is more important than gaining extra safety and peace of mind on every single function I write, then I'll give up on #2. But no one has done that yet. And I suspect the only way we'll find out is actually going through the exercise of converting code to work with const default. So here's a suggestion/challenge. We don't have to wait for Walter. Pick your favorite small, well contained C++ or D library and just try to rewrite it with const as default for parameters and use "inout" or "mutable" to tag modifiable arguments. You may not get everything right, but if you take the time to reason through it like a "human compiler" it should be close enough to see what the change would be like. In some professions they don't have the luxury of a magic program to tell them whether what they write is correct or not, so they do things the old fashioned way -- they use their brains. In fact that's probably the case in most every profession besides computer science. We have it easy. :-) --bb
Jun 10 2007
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 * "having same type defaults is better for generics"
   (maybe...but I'm not convinced. If you have powerful enough 
 metaprogramming it shouldn't be hard to strip const from a type tuple, 
 or add it.  And people do far more programming than meta-programming.)

This is a good point. With const-by-default, you have function type declarations behaving *fundamentally* different from other declarations. Given the metaprogramming ability to use tuples to declare parameters, doing function template type deduction for parameters, and type inference on parameters, making this fundamentally different may wind up really screwing things up.
Jun 10 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 * "having same type defaults is better for generics"
   (maybe...but I'm not convinced. If you have powerful enough 
 metaprogramming it shouldn't be hard to strip const from a type tuple, 
 or add it.  And people do far more programming than meta-programming.)

This is a good point. With const-by-default, you have function type declarations behaving *fundamentally* different from other declarations. Given the metaprogramming ability to use tuples to declare parameters, doing function template type deduction for parameters, and type inference on parameters, making this fundamentally different may wind up really screwing things up.

Yes, it's a good point (it's David Held's point), but again your argument is "may wind up really screwing things up". On the other hand it may wind up *not* screwing things up. Gut feelings are great, but neither you nor David have given any concrete examples. So let's look at a callback library like std.signals. With std.signals we do something like: mixin Signal!(char[], int); And the call signature for slots becomes void delegate(char[],int). To get only requires a simple variadic tuple parameter: template Signal(T1...) { alias void delegate(T1) slot_t; . . . } With const default it will be a little more annoying because it doesn't make sense to have const be the default for template paramters. So the user would need to say something like: mixin Signal!(in char[], in int); But if the only transformation is stickig 'in' on everything a template can be made to do that. So just something like... mixin Signal!(ParameterTuple(char[], int)); But what if the user actually wants some parameter to be mutable? Like a ref int instead of an int. There would have to be some keyword to mean 'make it mutable' in any event for const default. So just make our ParameterTuple metafunction smart enough not to override that. Maybe keep inout for this: mixin Signal!(ParameterTuple(char[], inout int)); And rememeber that signals are *used* much more frequently than they are defined. Users of the signal won't have to think about it, they'll just write their function: void cb(char[], inout int) { . . . } and it'll work. So that's a realistic case of wanting to take a regular tuple, and needing it to be a parameter tuple. And it doesn't look like it would really screw things up so far. But how about the other way? Say now we extract a parameter tuple from a function and we want to make a value tuple out of it we can use to call the function. void call(slot_t someslot) { alias std.traits.ParameterTypeTuple(slot_t) ArgTup; ArgTup args; args[0] = "Hi there"; args[1] = 5; someslot(args); } That won't work if slot_t's argument type tuple is all "constipated". But this should be doable too, I would think. Just something like a ValueTypeTuple(ArgTup). But even if that's not possible, you're going to have the _exact_ same problem with any form of const when trying to convert an argument tuple into a tuple you can make a variable out of. So it's hardly a strike against const by default. Any comments? --bb
Jun 10 2007
next sibling parent reply Reiner Pope <some address.com> writes:
Bill Baxter wrote:
 Walter Bright wrote:
 Bill Baxter wrote:
 * "having same type defaults is better for generics"
   (maybe...but I'm not convinced. If you have powerful enough 
 metaprogramming it shouldn't be hard to strip const from a type 
 tuple, or add it.  And people do far more programming than 
 meta-programming.)

This is a good point. With const-by-default, you have function type declarations behaving *fundamentally* different from other declarations. Given the metaprogramming ability to use tuples to declare parameters, doing function template type deduction for parameters, and type inference on parameters, making this fundamentally different may wind up really screwing things up.

Yes, it's a good point (it's David Held's point), but again your argument is "may wind up really screwing things up". On the other hand it may wind up *not* screwing things up. Gut feelings are great, but neither you nor David have given any concrete examples. So let's look at a callback library like std.signals. With std.signals we do something like: mixin Signal!(char[], int); And the call signature for slots becomes void delegate(char[],int). To get only requires a simple variadic tuple parameter: template Signal(T1...) { alias void delegate(T1) slot_t; . . . } With const default it will be a little more annoying because it doesn't make sense to have const be the default for template paramters. So the user would need to say something like: mixin Signal!(in char[], in int); But if the only transformation is stickig 'in' on everything a template can be made to do that. So just something like... mixin Signal!(ParameterTuple(char[], int)); But what if the user actually wants some parameter to be mutable? Like a ref int instead of an int. There would have to be some keyword to mean 'make it mutable' in any event for const default. So just make our ParameterTuple metafunction smart enough not to override that. Maybe keep inout for this: mixin Signal!(ParameterTuple(char[], inout int)); And rememeber that signals are *used* much more frequently than they are defined. Users of the signal won't have to think about it, they'll just write their function: void cb(char[], inout int) { . . . } and it'll work. So that's a realistic case of wanting to take a regular tuple, and needing it to be a parameter tuple. And it doesn't look like it would really screw things up so far.

the ParameterTuple!() call inside the template, not at the call-site. As I argue further down, I actually think it should be part of the language core. I agree with what you have written. I've got another similar example: the hypothetical DeclareFunction template, to be used as: alias DeclareFunction!(int, "a", double, "d", "code") myFunction; // should be equivalent to // void myFunction(int a, double d) { code } // no matter if const-by-default or not Clearly in this example, the ParameterTuple!() call should be done within the template, not at the call-site. I would argue that this is the same for std.signals: the declaration syntax looks like that of a function, so you should be able to declare types like a function. But that's fine, we can manage that inside our template. In fact, many examples I can think of with tuples deserve the same treatment, because you are effectively defining the parameters of a function, so you want them to look like that. --- I think another problem arises with compile-time variadic functions: printf(T...)(T t) Walter raised a concern about type inference and const-by-default; perhaps he was referring to functions like this. But suppose that const wasn't default. Since printf doesn't modify its arguments, you should really write: printf(T...)(const(T) t) // or MakeEachTypeConst!(T) t so type deduction presents the same problem here either way. --- I've got my own thoughts on how to set up const-by-default, which are very similar to what you suggested with 'inout' and ParameterTuple!(). The main difference I suggest is making it language-supported, which allows for more type inference as well as a better abstraction for tuples. There are three basic details, and one little detail about compile-time variadic functions: 1. ---- Addition of mutable() type constructor to language. (Here, mutable(T) is effectively equivalent to inout(T) as you described it. However, I don't like the idea of overloading inout's meaning, and I think mutable is a more appropriate name). In addition to the type constructors, const(), invariant(), etc, add also mutable(T) which behaves identically to a non-const T (ie each is implicitly convertible to the other). Its importance lies in the fact that: const(mutable(T)) == mutable(T) whereas const(T) == const(T) otherwise This effectively allows you to describe three kinds of (parameter) types: mutable -- "this will be mutable no matter what" const -- "this will be const no matter what" <modifierless> -- "I'll let you, the library implementer, choose appropriately" 2. ---- Make type constructors apply recursively to type tuples In addition to this, if we have alias Tuple!(stuff) T; then const(T) == Tuple!( const(T[0]), const(T[1]), ...) and similarly for all the other type constructors. 3. ---- All function parameters (including tuple parameters) have an implicit const() This is the const-by-default bit. All function parameters have an implicit const() wrapped around the type. Mutable parameters then look like this: void foo ( mutable(Bar) ) {...} and inside the compiler we get mutable(Bar) -----> const(mutable(Bar)) -----> mutable(Bar) (as it is declared) (add the implicit const()) (apply the simplification rule) (Little detail) 4. ---- How compile-time variadic functions have IFTI The tuple is filled with the types from the call-site. Most of these will be unornamented, giving the function-writer the freedom to make them const or mutable as he/she chooses: printf(T...)(T t) {...} // remember the implicit const() ... const(char[]) a; char[] b; printf(3, b, "abc", a); // In printf, T is now Tuple!(int, char[], invariant(char[]), const(char[]) // and typeof(t) == typeof(const(T)) ----- The beauty is that this works exactly as you would expect for signal&slots: in fact, no change in the library is required for it to support const-by-default. If you wanted to write a 'retro' signal&slots library which *didn't* have const-by-default, you could do that, too: template Signal(T1...) { alias void delegate(mutable(T1)) slot_t; ... } And, whereas details 1-3 could be done with template magic, supporting it in the language allows IFTI for compile-time variadic functions (like printf).
 
 
 But how about the other way?  Say now we extract a parameter tuple from 
 a function and we want to make a value tuple out of it we can use to 
 call the function.
 void call(slot_t someslot) {
    alias  std.traits.ParameterTypeTuple(slot_t) ArgTup;
    ArgTup args;
    args[0] = "Hi there";
    args[1] = 5;
    someslot(args);
 }
 
 That won't work if slot_t's argument type tuple is all "constipated".
 But this should be doable too, I would think.  Just something like a 
 ValueTypeTuple(ArgTup).
 
 But even if that's not possible, you're going to have the _exact_ same 
 problem with any form of const when trying to convert an argument tuple 
 into a tuple you can make a variable out of.  So it's hardly a strike 
 against const by default.

I think this is an unlikely usage, and the problem is presented with and without const-by-default. To get rid of *all* the consts, you would probably have to do some kind of type introspection with lots of recursive static if (is T : const(U)) expressions, or something similar. -- Reiner
Jun 10 2007
parent Georg Wrede <georg nospam.org> writes:
Reiner Pope wrote:
 
 I agree with what you have written. I've got another similar example: 
 the hypothetical DeclareFunction template, to be used as:
 
 alias DeclareFunction!(int, "a", double, "d", "code") myFunction;
 // should be equivalent to
 // void myFunction(int a, double d) { code }
 // no matter if const-by-default or not

(Slightly off-topic, but) shouldn't alias DeclareFunction!(int, "a", double, "d", "code") myFunction; mean int myFunction(double d) { code } In other words, the return type would be the first parameter to DeclareFunction!(). If we really wanted to ignore the return type (as in your example), then we might want another name for the template. For a lack of a better name, I'd suggest DeclareProcedure, where this distinction is of course borrowed from Pascal. Actually there's a "typo" here, my line should of course be alias DeclareFunction!(int, double, "d", "code") myFunction; (No use naming the return value. :-) )
Jun 12 2007
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Walter Bright wrote:
 Bill Baxter wrote:
 * "having same type defaults is better for generics"
   (maybe...but I'm not convinced. If you have powerful enough 
 metaprogramming it shouldn't be hard to strip const from a type 
 tuple, or add it.  And people do far more programming than 
 meta-programming.)

This is a good point. With const-by-default, you have function type declarations behaving *fundamentally* different from other declarations. Given the metaprogramming ability to use tuples to declare parameters, doing function template type deduction for parameters, and type inference on parameters, making this fundamentally different may wind up really screwing things up.

Yes, it's a good point (it's David Held's point), but again your argument is "may wind up really screwing things up". On the other hand it may wind up *not* screwing things up. Gut feelings are great, but neither you nor David have given any concrete examples.

The problem is that metaprogramming is in its infancy. I don't know a case that will screw up, but there's not a lot of metaprogramming out there. Any sort of glaring inconsistency in how declarations work is a potential future train wreck. It reminds me a bit of how people argued that using < > for template arguments would be fine, it was just a minor inconsistency. It wasn't, as the inconsistency threw wrench after wrench into the gears of later ideas, and eventually forced several wacky syntactical workarounds.
Jun 10 2007
next sibling parent reply Don Clugston <dac nospam.com.au> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 Walter Bright wrote:
 Bill Baxter wrote:
 * "having same type defaults is better for generics"
   (maybe...but I'm not convinced. If you have powerful enough 
 metaprogramming it shouldn't be hard to strip const from a type 
 tuple, or add it.  And people do far more programming than 
 meta-programming.)

This is a good point. With const-by-default, you have function type declarations behaving *fundamentally* different from other declarations. Given the metaprogramming ability to use tuples to declare parameters, doing function template type deduction for parameters, and type inference on parameters, making this fundamentally different may wind up really screwing things up.

Yes, it's a good point (it's David Held's point), but again your argument is "may wind up really screwing things up". On the other hand it may wind up *not* screwing things up. Gut feelings are great, but neither you nor David have given any concrete examples.

The problem is that metaprogramming is in its infancy. I don't know a case that will screw up, but there's not a lot of metaprogramming out there. Any sort of glaring inconsistency in how declarations work is a potential future train wreck. It reminds me a bit of how people argued that using < > for template arguments would be fine, it was just a minor inconsistency. It wasn't, as the inconsistency threw wrench after wrench into the gears of later ideas, and eventually forced several wacky syntactical workarounds.

That's true, but I'm not convinced that this is analogy is appropriate. There is a symmetry between 'const by default' and 'mutable by default'. C++ style const is a disaster for metaprogramming. Avoiding 'const-by-default' is no guarantee that trains stay on the rails. Secondly, it seems to me that CTFE will supplant the overwhelming majority of uses of template metaprogramming, especially when macros come along. If there is a merger between compile-time and run-time reflection (eg, unified syntax between static if(is(xxx)) and if(typeinfo(xxx)), allowing is() expressions inside CTFE functions, even more uses of templates would drop out. If const-by-default is OK for normal functions (including CTFE), I find it hard to believe it would be particularly problematic for metaprogramming. I can see so many benefits for const-by-default, and it is far more intuitive (when I originally read the descriptions of 'in', 'out', 'inout' in the spec, I thought that D uses const-by-default!) -- so I think we really need to be certain that const-by-default is not possible. I keep thinking of examples like: struct A { B b; C c; } and wanting to create an opCall-style constructor. I want to create a function of the form A func(A.tupleof params); In the normal case, I don't want to modify any of the parameters. So they should all be const. With mutable-by-default, it's necessary to add 'const' to all of the tuple elements; it definitely adds _some_ complication to the most common case for metaprogramming. The argument seems to be that const-by-default would make the less common metaprogramming case unbearably horrible. I'd like some evidence for this. At least a hint that it's worse than mutable-by-default. In the absence of any evidence against it, my vote lies strongly with const-by-default.
Jun 11 2007
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Don Clugston wrote:
 If const-by-default is OK for normal functions (including CTFE), I find 
 it hard to believe it would be particularly problematic for 
 metaprogramming.

We just don't know.
 I can see so many benefits for const-by-default, and it is far more 
 intuitive (when I originally read the descriptions of 'in', 'out', 
 'inout' in the spec, I thought that D uses const-by-default!) -- so I 
 think we really need to be certain that const-by-default is not possible.
 
 I keep thinking of examples like:
 
 struct A {
   B b;
   C c;
 }
 
 and wanting to create an opCall-style constructor.
 I want to create a function of the form
 
 A func(A.tupleof params);
 
 In the normal case, I don't want to modify any of the parameters. So 
 they should all be const. With mutable-by-default, it's necessary to add 
 'const' to all of the tuple elements; it definitely adds _some_ 
 complication to the most common case for metaprogramming.

I think you should be able to do: A func(in A.tupleof params);
 The argument 
 seems to be that const-by-default would make the less common 
 metaprogramming case unbearably horrible. I'd like some evidence for 
 this. At least a hint that it's worse than mutable-by-default.

It's not that it's worse, it's that there's an inconsistency. Having a type mean one thing as a parameter and quite another as a local is probably going to be a problem.
 In the absence of any evidence against it, my vote lies strongly with 
 const-by-default.

Jun 11 2007
next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Walter,

 Don Clugston wrote:

 The argument seems to be that const-by-default would make the less
 common metaprogramming case unbearably horrible. I'd like some
 evidence for this. At least a hint that it's worse than
 mutable-by-default.
 

type mean one thing as a parameter and quite another as a local is probably going to be a problem.

How bad would it be to make const by default apply to all references including locals? If inout, ref, out and friends were considered to be part of the type then this would make thing the same everywhere. I'd be willing to consider that even if it means that some type tuples end up having types in them that can only be used as parameter types. alias T!(in int, out char[], ref float) args; void thing(args){...}
Jun 11 2007
parent "Bent Rasmussen" <incredibleshrinkingsphere gmail.com> writes:
I had the same thought.

Is const-by-default everywhere feasible?

It would certainly be consistent.

 How bad would it be to make const by default apply to all references 
 including locals?
 If inout, ref, out and friends were considered to be part of the type then 
 this would make thing the same everywhere.
 I'd be willing to consider that even if it means that some type tuples end 
 up having types in them that can only be used as parameter types.

 alias T!(in int, out char[], ref float) args;
 void thing(args){...}

 

Jun 11 2007
prev sibling next sibling parent Derek Parnell <derek psych.ward> writes:
On Mon, 11 Jun 2007 12:11:40 -0700, Walter Bright wrote:

 Don Clugston wrote:
 If const-by-default is OK for normal functions (including CTFE), I find 
 it hard to believe it would be particularly problematic for 
 metaprogramming.

We just don't know.

So how do we find out the answer to that?
 I can see so many benefits for const-by-default, and it is far more 
 intuitive (when I originally read the descriptions of 'in', 'out', 
 'inout' in the spec, I thought that D uses const-by-default!) -- so I 
 think we really need to be certain that const-by-default is not possible.
 
 I keep thinking of examples like:
 
 struct A {
   B b;
   C c;
 }
 
 and wanting to create an opCall-style constructor.
 I want to create a function of the form
 
 A func(A.tupleof params);
 
 In the normal case, I don't want to modify any of the parameters. So 
 they should all be const. With mutable-by-default, it's necessary to add 
 'const' to all of the tuple elements; it definitely adds _some_ 
 complication to the most common case for metaprogramming.

I think you should be able to do: A func(in A.tupleof params);

... and that is a problem that no one can ever solve, right?
 The argument 
 seems to be that const-by-default would make the less common 
 metaprogramming case unbearably horrible. I'd like some evidence for 
 this. At least a hint that it's worse than mutable-by-default.

It's not that it's worse, it's that there's an inconsistency. Having a type mean one thing as a parameter and quite another as a local is probably going to be a problem.

A problem with what? Are you concerned that it will confuse coders? Why? I have been coding under that paradigm for years and your fear of problems is unfounded. No-one coding in Euphoria has had a problem with the "inconsistancy" that function foo(integer A) integer B means that code calling foo() never has to worry about the parameter 'A' being changed by foo() and that foo() can play with 'B' til its heart's content. This is not a concept that actually confuses coders. Is it a problem re metaprogramming with tuples as parameters lists? Why? That is an obscure aspect of a little used technique. Are you sure that there is no way on earth that anyone can solve this "inconsistancy"? -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
Jun 11 2007
prev sibling next sibling parent Jascha Wetzel <firstname mainia.de> writes:
Walter Bright wrote:
 Don Clugston wrote:
 If const-by-default is OK for normal functions (including CTFE), I 
 find it hard to believe it would be particularly problematic for 
 metaprogramming.

We just don't know.

If these issues can only be solved through experiments, why not experiment? Since D 2.0 is a development branch now anyway, it could have a switch that enables const-by-default. A few months later we'll know more... Correct me if i'm wrong, but my understanding is that the CbD feature itself is easily implemented in the compiler. Therefore this shouldn't lead to a lot of potentially lost work.
Jun 12 2007
prev sibling parent Roberto Mariottini <rmariottini mail.com> writes:
Walter Bright wrote:
 Don Clugston wrote:

 I want to create a function of the form

 A func(A.tupleof params);

 In the normal case, I don't want to modify any of the parameters. So 
 they should all be const. With mutable-by-default, it's necessary to 
 add 'const' to all of the tuple elements; it definitely adds _some_ 
 complication to the most common case for metaprogramming.

I think you should be able to do: A func(in A.tupleof params);

 
 It's not that it's worse, it's that there's an inconsistency. Having a 
 type mean one thing as a parameter and quite another as a local is 
 probably going to be a problem.

What about stating that all function parameters are "in" by default? It should be fairly clear, then. Ciao
Jun 12 2007
prev sibling parent reply Georg Wrede <georg nospam.org> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 
 Walter Bright wrote:

 Bill Baxter wrote:

 * "having same type defaults is better for generics"
   (maybe...but I'm not convinced. If you have powerful enough 
 metaprogramming it shouldn't be hard to strip const from a type 
 tuple, or add it.  And people do far more programming than 
 meta-programming.)

This is a good point. With const-by-default, you have function type declarations behaving *fundamentally* different from other declarations.



True. See below.
 Given the metaprogramming ability to use tuples to 
 declare parameters, doing function template type deduction for 
 parameters, and type inference on parameters, making this 
 fundamentally different may wind up really screwing things up.

Yes, it's a good point (it's David Held's point), but again your argument is "may wind up really screwing things up". On the other hand it may wind up *not* screwing things up. Gut feelings are great, but neither you nor David have given any concrete examples.

The problem is that metaprogramming is in its infancy. I don't know a case that will screw up, but there's not a lot of metaprogramming out there. Any sort of glaring inconsistency in how declarations work is a potential future train wreck. It reminds me a bit of how people argued that using < > for template arguments would be fine, it was just a minor inconsistency. It wasn't, as the inconsistency threw wrench after wrench into the gears of later ideas, and eventually forced several wacky syntactical workarounds.

I think parameter passing is a world separate from "other const or const-as-default" areas. Thus, having parameters behave differently from them poses no risk for confusion, and, IMHO, is a conceptually clean and intuitive choice. It also has a crystal clear perimeter, which dramatically reduces the mental strain of having to remember things.
Jun 12 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Georg,

 I think parameter passing is a world separate from "other const or
 const-as-default" areas. Thus, having parameters behave differently
 from them poses no risk for confusion, and, IMHO, is a conceptually
 clean and intuitive choice. It also has a crystal clear perimeter,
 which dramatically reduces the mental strain of having to remember
 things.
 

The issue is that a and b in this code are of different types if T is a reference type and that same type otherwise. |void TFn(T)(T a) |{ | T b; |}
Jun 12 2007
parent reply Georg Wrede <georg nospam.org> writes:
BCS wrote:
 Reply to Georg,
 
 I think parameter passing is a world separate from "other const or
 const-as-default" areas. Thus, having parameters behave differently
 from them poses no risk for confusion, and, IMHO, is a conceptually
 clean and intuitive choice. It also has a crystal clear perimeter,
 which dramatically reduces the mental strain of having to remember
 things.

The issue is that a and b in this code are of different types if T is a reference type and that same type otherwise. |void TFn(T)(T a) |{ | T b; |}

(Disclaimer: I've been out of town some, so I might have missed something important relating to this.) Within the function (prototype or not), T a would be a read-only variable and T b would be the correspoinding read/write variable. Could you give me an example where this does pose a problem?
Jun 12 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Georg Wrede wrote:
 BCS wrote:
 Reply to Georg,

 I think parameter passing is a world separate from "other const or
 const-as-default" areas. Thus, having parameters behave differently
 from them poses no risk for confusion, and, IMHO, is a conceptually
 clean and intuitive choice. It also has a crystal clear perimeter,
 which dramatically reduces the mental strain of having to remember
 things.

The issue is that a and b in this code are of different types if T is a reference type and that same type otherwise. |void TFn(T)(T a) |{ | T b; |}

(Disclaimer: I've been out of town some, so I might have missed something important relating to this.) Within the function (prototype or not), T a would be a read-only variable and T b would be the correspoinding read/write variable. Could you give me an example where this does pose a problem?

I think the big trouble here comes just from having const at all, not because of it being the default. void TFn(T)(T a) { T b; } If T is a reference type and you want a to be const, and b to not be const, then you've got some explaining to do either way. But probably the most common case is that you want the parameter to be non-modifiable and the local variable to be modifiable. And there const by default works. There is a question about how to handle IFTI, which I believe the other const-by-default examples (Perl6 and Euphoria) probably don't have to deal with. The question is should this: int x; TFn(&x); deduce T as const-final-scope int* or just plain int*. Regardless of the const-by-default issue, D will need a simple way to go back and forth between 'in T' and 'mutable T' so I think deciding that IFTI works either way would be fine. But the IFTI issue definitely needs some more thinking. --bb
Jun 12 2007
parent reply Georg Wrede <georg nospam.org> writes:
Bill Baxter wrote:
 Georg Wrede wrote:
 
 BCS wrote:

 Reply to Georg,

 I think parameter passing is a world separate from "other const or
 const-as-default" areas. Thus, having parameters behave differently
 from them poses no risk for confusion, and, IMHO, is a conceptually
 clean and intuitive choice. It also has a crystal clear perimeter,
 which dramatically reduces the mental strain of having to remember
 things.

The issue is that a and b in this code are of different types if T is a reference type and that same type otherwise. |void TFn(T)(T a) |{ | T b; |}

(Disclaimer: I've been out of town some, so I might have missed something important relating to this.) Within the function (prototype or not), T a would be a read-only variable and T b would be the correspoinding read/write variable. Could you give me an example where this does pose a problem?

I think the big trouble here comes just from having const at all, not because of it being the default. void TFn(T)(T a) { T b; } If T is a reference type and you want a to be const, and b to not be const, then you've got some explaining to do either way. But probably the most common case is that you want the parameter to be non-modifiable and the local variable to be modifiable. And there const by default works. There is a question about how to handle IFTI, which I believe the other const-by-default examples (Perl6 and Euphoria) probably don't have to deal with. The question is should this: int x; TFn(&x); deduce T as const-final-scope int* or just plain int*. Regardless of the const-by-default issue, D will need a simple way to go back and forth between 'in T' and 'mutable T' so I think deciding that IFTI works either way would be fine. But the IFTI issue definitely needs some more thinking.

Suppose we consider a function to be a soap bubble. Variables declared inside it are r/w unless the programmer for some reason wants otherwise. And the variables that are arguments to this function are read-only, as seen from within the function, unless the author wants to specifically declare them otherwise. Let's first think about functions without side effects, and then functions with side effects. A function without side effects reads stuff from the arguments, manipulates the values and then possibly returns a result. During this manipulation, the arguments are only used to hold the parameters given to the function, and every time arithmetic or something is done to them, the result is stored into a local variable. The result of the function is stored in a local (possibly implicit) variable that is then passed as the return value. Such return values are treated as read-only by the calling function because in C family languages they are stored on the stack, and thus have to be directly assigned to a variable (or an implicit variable, say in an arithmetic context, like the return value of sin(x)) or else the value is lost. Currently I can't find any problem with this. Then we have the functions with side effects. These functions can affect either their arguments, or something "external", like memory or IO. Let's look at modifying arguments. The trival example is inc(x). When passed a value, it modifies the value and exits. Still simple. But what happens when it is passed a reference to a value? Should it be able to change the reference or the referree? Or both? One could spend weeks pondering on this, with numerous examples for any of the three possibilities. But I think such pondering is besides the point. (!) The one important distinction is whether _anything_ gets changed via the argument mechanism, or not. In other words, either a function does not touch what it gets, or then it does. What it does change is very much less important than the fact itself that it does. If we accept this line of thinking, then we have, on one side, the functions that don't, and which thus can be "relied upon" and also optimised during compilation. On the other side we have the functions that do, and for which the programmer has to consult documentation or source code -- or simply understand from the context (as with inc(x), where the intent is self evident) what is going to be modified. At this point I'm not sure there is a genuine need to have the compiler make a distinction between modifying a reference itself or the pointed-to value. (Anybody having a good counter example is welcome here.) At any rate, only having the single distinction between argument modifying and non-modifying is immensely useful. We get most of the candy with just two cents, whereas placing restrictions between the different ways of modifying stuff via an argument does cost bucks and it brings only small incremental benefits. (C++ gives you choices we don't need: strap yourself immobile, shoot yourself in the foot, or drown in the sea of implications.) KISS. Now, to the functions that modify stuff "outside" the arguments. A trivial example would be a function that changes the system time, setTime(y,m,d,h,m,s). None of the arguments as such are modified, but something else is. (There are also functions that both modify their arguments and modify "outside stuff". They don't need to be addressed here separately.) Conclusion For the purposes of language development, we now have two attributes for each function: does it change its arguments, and does it change anything else. I'd actually like to have these incorporated into the function signature. A function can only be Pure if all the functions it calls are Pure (i.e. do not change anything) and it is Pure itself. It might be useful to have "does chanege its arguments" as a flag which can quickly be checked during compilation, even if it is deducable from the argument declarations. This may speed things up. But the *more* important flag would be whether the function may change "external" things. This is hard to see without a flag in the signature. I see that pure functions will gain more importance in the near future of D, and therefore we should prepare for it now with this flag.
Jun 13 2007
parent reply eao197 <eao197 intervale.ru> writes:
On Wed, 13 Jun 2007 16:13:01 +0400, Georg Wrede <georg nospam.org> wrote:

<...skipped...>

 Conclusion

 For the purposes of language development, we now have two attributes for  
 each function: does it change its arguments, and does it change anything  
 else. I'd actually like to have these incorporated into the function  
 signature. A function can only be Pure if all the functions it calls are  
 Pure (i.e. do not change anything) and it is Pure itself.

That all is already in C++: class Demo { public : // Does not change anything in the Demo instance. void f() const; // Changes something in the Demo instance. void f1(); // Does not change any argument. // Changes something in the Demo instance. void f2( int a, const char * b, const Something & c ); // Does not change any argument. // Does not change anything in the Demo instance. void f3( int a, const char * b, const Something & c ) const; // Changes a, b and c. // Changes something in the Demo instance. void f4( int & a, char * b, Something & c ); // Changes a, b and c. // Does not change anything in the Demo instance. void f5( int & a, char * b, Something & c ) const; }; Yes, there are possible changes to some global variables or to mutable members of Demo.
 It might be useful to have "does chanege its arguments" as a flag which  
 can quickly be checked during compilation, even if it is deducable from  
 the argument declarations. This may speed things up. But the *more*  
 important flag would be whether the function may change "external"  
 things. This is hard to see without a flag in the signature.

I think if someone want to have 'pure functions' then it is better to look to functional programming languages. -- Regards, Yauheni Akhotnikau
Jun 13 2007
parent reply Don Clugston <dac nospam.com.au> writes:
eao197 wrote:
 On Wed, 13 Jun 2007 16:13:01 +0400, Georg Wrede <georg nospam.org> wrote:
 
 <...skipped...>
 
 Conclusion

 For the purposes of language development, we now have two attributes 
 for each function: does it change its arguments, and does it change 
 anything else. I'd actually like to have these incorporated into the 
 function signature. A function can only be Pure if all the functions 
 it calls are Pure (i.e. do not change anything) and it is Pure itself.

That all is already in C++: class Demo { public : // Does not change anything in the Demo instance. void f() const; // Changes something in the Demo instance. void f1(); // Does not change any argument. // Changes something in the Demo instance. void f2( int a, const char * b, const Something & c ); // Does not change any argument. // Does not change anything in the Demo instance. void f3( int a, const char * b, const Something & c ) const; // Changes a, b and c. // Changes something in the Demo instance. void f4( int & a, char * b, Something & c ); // Changes a, b and c. // Does not change anything in the Demo instance. void f5( int & a, char * b, Something & c ) const; }; Yes, there are possible changes to some global variables or to mutable members of Demo.

It's worse than that. You can call any global function, or any static function of any class. eg, deleteAllFilesOnHardDisk(); Moreover, you can const_cast<> and change anything at all. C++ const gives you no guarantees whatsoever.
 It might be useful to have "does chanege its arguments" as a flag 
 which can quickly be checked during compilation, even if it is 
 deducable from the argument declarations. This may speed things up. 
 But the *more* important flag would be whether the function may change 
 "external" things. This is hard to see without a flag in the signature.

I think if someone want to have 'pure functions' then it is better to look to functional programming languages.

And it's one of the good ideas from functional programming languages. Note that any pure function is a candidate for CTFE (if called with constant arguments), so it's becoming useful for D.
Jun 13 2007
parent reply eao197 <eao197 intervale.ru> writes:
On Wed, 13 Jun 2007 17:30:27 +0400, Don Clugston <dac nospam.com.au> wrote:

 It might be useful to have "does chanege its arguments" as a flag  
 which can quickly be checked during compilation, even if it is  
 deducable from the argument declarations. This may speed things up.  
 But the *more* important flag would be whether the function may change  
 "external" things. This is hard to see without a flag in the signature.

look to functional programming languages.

And it's one of the good ideas from functional programming languages. Note that any pure function is a candidate for CTFE (if called with constant arguments), so it's becoming useful for D.

But why trying to transform D to a functional language instead of use one of such languages? -- Regards, Yauheni Akhotnikau
Jun 13 2007
next sibling parent sambeau (Sam Phillips) <spam_sambeau mac.com> writes:
eao197 Wrote:

 But why trying to transform D to a functional language instead of use one  
 of such languages?

</lurk> Automatic parallelization. http://en.wikipedia.org/wiki/Automatic_parallelization See also 'data dependancies'. With today's multicore chips this is becoming more and more of an issue. Especially in the gaming (and most especially sony cell/PS3) world. <lurk>
Jun 13 2007
prev sibling parent "Bent Rasmussen" <incredibleshrinkingsphere gmail.com> writes:
The nice thing about D is that it is a multi paradigm language*, but in 
order to remain relevant in the future it has to cater for parallelism - if 
not, I suspect noone will be interested in how fast its programs run on a 
single-core processor when they have massively parallel many-core processors 
with 200 cores or more. Now maybe automatic parallelization is going to be 
sufficient, and maybe local or parameter constness is not a big issue, I 
don't know, but there is also some merrit to the disclipline and clarity of 
constness. In "unpure" functional languages like *ML, there's a ref (If I 
recall correctly) that denote variables and a val for constants, which is 
the norm. Types are inferred and life is good. There is no shame in being 
inspired, as long as it doesn't opens up a major crack of inconsistency in 
the language.

My cent.

Bent

* The same could be said of O'Caml of course, with its objects.


"eao197" <eao197 intervale.ru> wrote in message 
news:op.ttvbwaemsdcfd2 eao197nb2.intervale.ru...
 On Wed, 13 Jun 2007 17:30:27 +0400, Don Clugston <dac nospam.com.au> 
 wrote:

 It might be useful to have "does chanege its arguments" as a flag 
 which can quickly be checked during compilation, even if it is 
 deducable from the argument declarations. This may speed things up. 
 But the *more* important flag would be whether the function may change 
 "external" things. This is hard to see without a flag in the signature.

look to functional programming languages.

And it's one of the good ideas from functional programming languages. Note that any pure function is a candidate for CTFE (if called with constant arguments), so it's becoming useful for D.

But why trying to transform D to a functional language instead of use one of such languages? -- Regards, Yauheni Akhotnikau

Jun 13 2007
prev sibling parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 * "having same type defaults is better for generics"
   (maybe...but I'm not convinced. If you have powerful enough 
 metaprogramming it shouldn't be hard to strip const from a type tuple, 
 or add it.  And people do far more programming than meta-programming.)

This is a good point. With const-by-default, you have function type declarations behaving *fundamentally* different from other declarations. Given the metaprogramming ability to use tuples to declare parameters, doing function template type deduction for parameters, and type inference on parameters, making this fundamentally different may wind up really screwing things up.

Will using tuples to declare function parameters allow us to declare ref/inout parameters? -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jun 11 2007
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Bruno Medeiros wrote:
 Walter Bright wrote:
 Bill Baxter wrote:
 * "having same type defaults is better for generics"
   (maybe...but I'm not convinced. If you have powerful enough 
 metaprogramming it shouldn't be hard to strip const from a type 
 tuple, or add it.  And people do far more programming than 
 meta-programming.)

This is a good point. With const-by-default, you have function type declarations behaving *fundamentally* different from other declarations. Given the metaprogramming ability to use tuples to declare parameters, doing function template type deduction for parameters, and type inference on parameters, making this fundamentally different may wind up really screwing things up.

Will using tuples to declare function parameters allow us to declare ref/inout parameters?

Nevermind, seems you already confirmed that in another post:
 That's true, and it's one of the big motivators to support 'ref', as
 then it becomes possible to make the parameter list a type tuple.

-- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jun 11 2007
prev sibling next sibling parent "Bent Rasmussen" <incredibleshrinkingsphere gmail.com> writes:
const-by-default. That is just my feeling. But I'm sure there is a well 
thought-out reason not to do it... 
Jun 10 2007
prev sibling next sibling parent Carlos Santander <csantander619 gmail.com> writes:
Jarrett Billingsley escribió:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too 
 weird."
 
 Please reply with your choice, and maybe a small explanation of why.
 
 I'll start this off by saying I'm definitely willing to try option 2.  I 
 never really learned const-correctness in C++ because it looked so damned 
 awful.  Option 2 makes more sense to me. 
 
 

I vote 2 because of having safety as default. Plus, it would only be a try. If it doesn't work, we can try something else. -- Carlos Santander Bernal
Jun 10 2007
prev sibling next sibling parent Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jarrett Billingsley schrieb am 2007-06-10:
 This is not a discussion thread.  I think we've discussed enough.  :)

 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):

 1) C++ style const, where you mark anything that should be const as such.

 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.

2) const-by-default I think that const-by-default would result in less complex functions - and thus much more maintainable ones - than mutable-by-default. This impression is based what I've see in C++ code, however there are so many factors at play that a statistical prove is very difficult if not impossible. Thomas -----BEGIN PGP SIGNATURE----- iQIVAwUBRmxkBbZlboUnBhRKAQK+vRAAg/x3P3xFt1T+BPRnT6kzuHmKfcJwJmUA xJ1IbOVAfsnXYXSQxAXWiMFtTS1BSG35BgmloiXzuQJBtzk/c8FvleVt9BumU646 68MRo5rNQJUm02t8ujAM8ADEC3MnjKv7dV5e6zc0OwvFcFv10b4+SV2hdOu3nL3z ASLu57ZYFwOvC6VXKYgKdZK3ym7qyGRh5wledKFuh+nXX+KC3BHJTirmEHMr1eyb YvOi384ILxfOZhiyUdMgfS9QUB6cIb+SsLx78g3yXM6kj1QRd/vjgyKv3Q+zlQTh mRlfIB9VUjJvBWy7tgnxuv/9z3QyXDCG2vvGgGI1AkQMeTu3zSuabAGwytdYrRrv z18BxdMrYGF08C1pHDieWs+3+xV7Zkid3iXpBr6qrDiddpnzr0XdSW5Xju1M3+iN vKtP7TMh1Mi7+UavuHMKUZz3rX8clq1ewlt+U6ni7VznxumQ3PrUKr8MTfjnNhIe cpI6szL4pD82heI26LOzjxp05gAeeAcaYidTgqfCW0j/D90tsPkL4UN+gHB7ha25 B/ZDc7viHYTdRXkkc/GgXKE4PZEbnHp508n1iT/PxTg3qT9lIEaED42aaeKZ40e/ PGJriUljKwjkHi1wV9GLPDkbDylAdpL2GCjopP5d0sTpb7FTTZTD2s56kG/grOFM dUv+HrALFwQ= =AK6Q -----END PGP SIGNATURE-----
Jun 10 2007
prev sibling next sibling parent Frank Benoit <keinfarbton googlemail.com> writes:
I have lots of D code. And i would be happy to spend a week to constify
everything. But the only way is const by default, because here the
compiler shows me the way.

one more vote for const-by-default.
Jun 10 2007
prev sibling next sibling parent gareis <dhasenan gmail.com> writes:
Jarrett Billingsley wrote:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too 
 weird."
 
 Please reply with your choice, and maybe a small explanation of why.

Doubt it makes much difference, but I prefer having function arguments be scope final const by default. Instead of seeing 'in' on a function signature and knowing I'm safe calling it with my precious data, I know that my data's safe unless I'm explicitly told otherwise. Though T[new] is a different story entirely.
Jun 10 2007
prev sibling next sibling parent reply Jeff Nowakowski <jeff dilacero.org> writes:
Jarrett Billingsley wrote:
 Please reply with your choice, and maybe a small explanation of why.

Option 2, and I'll quote Walter: "Having const will reduce the problem by bringing the documentation into the semantic information of the code, and so reduce the need for code reviews in the future." Functions with side-effects should be marked as such. Let the compiler help. -Jeff
Jun 10 2007
parent Leandro Lucarella <llucax gmail.com> writes:
Option 2) because of...

Jeff Nowakowski, el 10 de junio a las 17:34 me escribiste:
 Functions with side-effects should be marked as such.  Let the compiler help.

-- LUCA - Leandro Lucarella - Usando Debian GNU/Linux Sid - GNU Generation ------------------------------------------------------------------------ E-Mail / JID: luca lugmen.org.ar GPG Fingerprint: D9E1 4545 0F4B 7928 E82C 375D 4B02 0FE0 B08B 4FB2 GPG Key: gpg --keyserver pks.lugmen.org.ar --recv-keys B08B4FB2 ------------------------------------------------------------------------ Hey you, standing in the road always doing what you're told, Can you help me?
Jun 11 2007
prev sibling next sibling parent Charlie <charlie.fats gmail.com> writes:
2 gets my vote!

Also i love how involved the community is, its good to see people 
vocalize their wants ( <nudge> Walter </nudge> ) , shows they have a 
real investment in D and how it turns out.

Charlie

Jarrett Billingsley wrote:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too 
 weird."
 
 Please reply with your choice, and maybe a small explanation of why.
 
 I'll start this off by saying I'm definitely willing to try option 2.  I 
 never really learned const-correctness in C++ because it looked so damned 
 awful.  Option 2 makes more sense to me. 
 
 

Jun 10 2007
prev sibling next sibling parent Daniel Giddings <daniel.giddings gmail.com> writes:
One more vote for const by default here. With C++ programming, having to 
use const with parameters correctly is a real pain.


Jarrett Billingsley wrote:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 

Jun 10 2007
prev sibling next sibling parent reply "Rioshin an'Harthen" <rharth75 hotmail.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> kirjoitti viestissä 
news:f4h2s9$qm8$1 digitalmars.com...
 This is not a discussion thread.  I think we've discussed enough.  :)

 Basically there are these possible const implementations (there are 
 others, but for the sake of simplicitly, I'll keep this poll to 2):

 1) C++ style const, where you mark anything that should be const as such.

 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.

 Walter doesn't want to stray from option 1, because 2 is basically "too 
 weird."

 Please reply with your choice, and maybe a small explanation of why.

I'd definitely go for option 2 - having had to code const correct C++, I know what kind of a pain it is. Much simpler to have every parameter be const by default and add mutable/variant etc. in front of those the compiler complains about. Voila! Automatically const correct code.
Jun 11 2007
parent torhu <fake address.dude> writes:
Rioshin an'Harthen wrote:
 
 I'd definitely go for option 2 - having had to code const correct C++, I 
 know
 what kind of a pain it is. Much simpler to have every parameter be const by
 default and add mutable/variant etc. in front of those the compiler 
 complains
 about. Voila! Automatically const correct code. 
 

'var' is shorter than 'mutable', so that might be a good option for a keyword in this case. Depends if D is going to adopt the C++ 'mutable' concept, in that case reusing mutable might be a better option. Pascal uses 'var' for out parameters, but it works like inout or ref in D, not quite like the intended meaning of mutable in D. But still...
Jun 11 2007
prev sibling next sibling parent eao197 <eao197 intervale.ru> writes:
On Sun, 10 Jun 2007 18:46:40 +0400, Jarrett Billingsley  =

<kb3ctd2 yahoo.com> wrote:

 1) C++ style const, where you mark anything that should be const as su=

I vote for this.
 2) Parameters are const-by-default, and must be marked mutable otherwi=

 Locals, fields etc. are still mutable by default.

As for me this option seems strange in some cases. For example: class Logger { // Non-const methods. void fatal( char[] message ); void error( char[] message ); ... } class ExecutionContext { // There an instance of Logger is not const. Logger logger_; this( // But there an instance of logger is const. Logger logger ) { logger_ =3D cast(Logger) logger; ... } } I easily can understand code like: class ExecutionContext { mutable Logger logger_; // or ref Logger logger_; this( mutable Logger logger ) { ... } } or class ExecutionContext { const Logger logger_; this( const Logger logger ) { ... } } when type declarations for fields and parameters are the same. -- = Regards, Yauheni Akhotnikau
Jun 11 2007
prev sibling next sibling parent Stephen Waits <steve waits.net> writes:
I vote 2: const-by-default.  But this needs a LOT more thinking.

The derivative of D's complexity seems to still be climbing.  That's bad.

No matter what though, one thing I think is an absolutely horrible idea 
is doing anything even remotely similar to the C++ const mess.  I've 
been there, done that.  In fact, a few years ago I had a programmer on 
the "const trip", and he said "you'll thank me in a few years".  Well, a 
few years later I painfully undid all of that crap and I certainly 
wasn't thanking him!

Also, I asked Paris Hilton what she thought about this, and she said, 
"C++ const totally sucks, I hate that bitch! Wahh!".  Then she cried 
some more and went to jail.

--Steve
Jun 11 2007
prev sibling next sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
I'm rather against the whole constness concept in general, but I think by
default would be a lot easier than trying to think through whether I've changed
something or not. So, while I used to think the first would be better, you've
all convinced me -- option 2. If it doesn't work out in the alpha, it doesn't
work out in the alpha, and we switch back.

Here's another option I'm sure has been mentioned: what about a compiler switch
for default "in" vs. default "var" (I agree that "mutable" is way too long to
type all the time)?

Jarrett Billingsley Wrote:

 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too 
 weird."
 
 Please reply with your choice, and maybe a small explanation of why.
 
 I'll start this off by saying I'm definitely willing to try option 2.  I 
 never really learned const-correctness in C++ because it looked so damned 
 awful.  Option 2 makes more sense to me. 
 
 

Jun 11 2007
prev sibling next sibling parent Myron Alexander <someone somewhere.com> writes:
My coding style screams 'const by default' but Walter raises some 
interesting points so I just have to say that I don't know.

Walter, I do feel it is worth trying const by default in a build and 
seeing how existing code is affected by it. I think that the only way to 
be sure is to experiment and base the final decision on the results. 
This will only work if as many people as possible stress the build, 
looking for conceptual weak points and then coming together with the 
results.

Regards,

Myron.
Jun 11 2007
prev sibling next sibling parent Ary Manzana <ary esperanto.org.ar> writes:
Jarrett Billingsley escribió:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too 
 weird."
 
 Please reply with your choice, and maybe a small explanation of why.
 
 I'll start this off by saying I'm definitely willing to try option 2.  I 
 never really learned const-correctness in C++ because it looked so damned 
 awful.  Option 2 makes more sense to me. 
 
 

2) const by default. Most of the time a program transforms data: T1 var1 = someVar.doSomething(); if (var1.hasProperty()) { T2 var2 = var1.doSomethingElse(); return var2.foo(); } else { T2 var2 = var1.doSomethingDifferent(); return var2.bar(); } At least high level programs, I guess. Maybe even var1 is used afterwards for something else... and if it's mutable by default and some other programmer in my team comes and assigns a value to it in the middle, it may break something. Marking which variables are meant to change is safer, I think.
Jun 11 2007
prev sibling next sibling parent Georg Wrede <georg nospam.org> writes:
Jarrett Billingsley wrote:
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.

Most definitely 2. Even if we didn't consider this an experiment, I'd still vehemently vote for 2. And now that we have this "D2 experimental branch" I simply cannot imagine a valid reason for not trying it out. Of course, Phobos might require some man hours to compile, but hey, no pain no gain. Amusingly, what makes (2) different from most other fundamental language changes is, this is intuitive and self-evident even to most programming novices.
Jun 12 2007
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
Jarrett Billingsley wrote:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.

I'd like to at least try option 2. It sounds appealing in theory, but it's hard to say whether I'd actually like it without actually using it. My only stipulation is there there must be some way to do this: void fn( char[] a ) { a[0] = 'a'; } fn( ("xxx".dup)[0 .. 1] ); ie. pass a temporary array (slice, etc) as a parameter whose contents are modifiable. Sean
Jun 12 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message 
news:f4mjat$10c1$1 digitalmars.com...

 I'd like to at least try option 2.  It sounds appealing in theory, but 
 it's hard to say whether I'd actually like it without actually using it. 
 My only stipulation is there there must be some way to do this:

     void fn( char[] a ) { a[0] = 'a'; }

     fn( ("xxx".dup)[0 .. 1] );

 ie. pass a temporary array (slice, etc) as a parameter whose contents are 
 modifiable.

Oh absolutely. CbD kind of implies a "non-default" case where it wouldn't apply :)
Jun 12 2007
prev sibling next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Jarrett Billingsley wrote:

 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are
 others, but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise.
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too
 weird."
 
 Please reply with your choice, and maybe a small explanation of why.
 
 I'll start this off by saying I'm definitely willing to try option 2.  I
 never really learned const-correctness in C++ because it looked so damned
 awful.  Option 2 makes more sense to me.

I'd like to try 2) -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jun 12 2007
prev sibling next sibling parent kris <foo bar.com> writes:
Jarrett Billingsley wrote:
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 
 Walter doesn't want to stray from option 1, because 2 is basically "too 
 weird."
 
 Please reply with your choice, and maybe a small explanation of why.
 
 I'll start this off by saying I'm definitely willing to try option 2.  I 
 never really learned const-correctness in C++ because it looked so damned 
 awful.  Option 2 makes more sense to me. 

++ for option 2 It's worth trying at least? Tango is an extensive library, and would perhaps be a good proving ground for whether option 2 works well or not? Would take perhaps a day or less to convert all of Tango + Mango for experimental purposes? I'd jump at the chance to try it :)
Jun 12 2007
prev sibling next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
I want to see option #2, but I think more work needs to be done to
ensure that all the problems related to metaprogramming get resolved.
For instance, this has me worried:

void foo(T)(T a)
{
  T b;
}

foo(new Object);

What's T?  If T is "const Object", then you've broken the "const by
default on function arguments only" stipulation.  If it's "Object" then
the inferred type is one thing, and *actual type* the compiler sees is
different.  It's not exactly very pretty.

There's probably other nasties lurking around, which is why I originally
proposed the addition of a const by default switch as a purely temporary
measure to see what happens.

That said, if we can't have the switch, I still think we should give
const by default a shot if only to see what the full impact is.  If it
turns out to be too onerous, then we can roll back to non const by default.

So yeah; +1 on option 2, provided we can sort out any issues that code up.

	-- Daniel
Jun 12 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Daniel Keep wrote:
 I want to see option #2, but I think more work needs to be done to
 ensure that all the problems related to metaprogramming get resolved.
 For instance, this has me worried:
 
 void foo(T)(T a)
 {
   T b;
 }
 
 foo(new Object);
 
 What's T?  If T is "const Object", then you've broken the "const by
 default on function arguments only" stipulation.  If it's "Object" then
 the inferred type is one thing, and *actual type* the compiler sees is
 different.  It's not exactly very pretty.
 
 There's probably other nasties lurking around, which is why I originally
 proposed the addition of a const by default switch as a purely temporary
 measure to see what happens.
 
 That said, if we can't have the switch, I still think we should give
 const by default a shot if only to see what the full impact is.  If it
 turns out to be too onerous, then we can roll back to non const by default.
 
 So yeah; +1 on option 2, provided we can sort out any issues that code up.
 
 	-- Daniel

In the world of const though, really what you want is for that to become void foo(const Object a) { Object b; } So either way, const-by-default or not, you've got issues. In C++ I think that's usually spelled something like: template<T> void foo(const T a) { T b; } and foo(new Object) results in T being Object* and the function becoming void foo(const Object* a) { Object* b; } For D const-by-default I would expect foo(new Object) to get T set to Object, resulting in void foo(Object a) // param const-static-final as expected { Object b; // not const as expected. } Would anything else make sense? Similar to the C++ case, if you WANT something other than the default, then you'll need to say so in the argument: void foo(T)(mutable T a) { T b; } Now both a and b are modifiable in foo(new Object). Here's a real potential issue. How do you overload on const? void foo(Obj a) {...} // const by default void foo(mutable Obj a) {...} // modifiable foo(new Obj); ... or no. Actually that's not an issue either. You call the mutable one unless you can't. I'm starting to be hopeful that all these potential issues will just melt away under closer inspection (or at least turn out to be no more thorny for const-by-default than for const of any kind). --bb
Jun 12 2007
prev sibling next sibling parent Reiner Pope <some address.com> writes:
Jarrett Billingsley wrote:
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.

Jun 12 2007
prev sibling parent nobody nowhere.nonet writes:
Jarrett Billingsley <kb3ctd2 yahoo.com> spewed this unto the Network: 
 This is not a discussion thread.  I think we've discussed enough.  :)
 
 Basically there are these possible const implementations (there are others, 
 but for the sake of simplicitly, I'll keep this poll to 2):
 
 1) C++ style const, where you mark anything that should be const as such.
 
 2) Parameters are const-by-default, and must be marked mutable otherwise. 
 Locals, fields etc. are still mutable by default.
 

Option 2 is definitely better. -- Do unto others as they'd do unto you, but do it first!
Jun 14 2007