digitalmars.D - Poll: Would you like to try const-by-default or not?
- Jarrett Billingsley (12/12) Jun 10 2007 This is not a discussion thread. I think we've discussed enough. :)
- Johan Granberg (3/21) Jun 10 2007 Option 2 sounds like the choice to require less typing and is safer so 2...
- Deewiant (6/11) Jun 10 2007 Option 2, because it's easier to catch bugs with it.
- Derek Parnell (10/18) Jun 10 2007 No, thank you. Not that I'm an expert but this paradigm seems to be to h...
- Sebastian Beschke (4/8) Jun 10 2007 2.
- Roald Ribe (1/1) Jun 10 2007 Less typing AND safer in the end? It is a no brainer. 2
- Regan Heath (5/13) Jun 10 2007 vote for this one of course!
- Mandel (4/4) Jun 10 2007 I vote for 2.
- Bill Baxter (39/52) Jun 10 2007 I would really like to give option 2 a try too. I mean we have very
- Walter Bright (7/11) Jun 10 2007 This is a good point. With const-by-default, you have function type
- Bill Baxter (56/68) Jun 10 2007 Yes, it's a good point (it's David Held's point), but again your
- Reiner Pope (99/182) Jun 10 2007 I agree with your example, although I would think it makes sense to put
- Georg Wrede (14/22) Jun 12 2007 (Slightly off-topic, but) shouldn't
- Walter Bright (9/28) Jun 10 2007 The problem is that metaprogramming is in its infancy. I don't know a
- Don Clugston (32/62) Jun 11 2007 That's true, but I'm not convinced that this is analogy is appropriate. ...
- Walter Bright (7/37) Jun 11 2007 I think you should be able to do:
- BCS (9/19) Jun 11 2007 How bad would it be to make const by default apply to all references inc...
- Bent Rasmussen (3/12) Jun 11 2007 I had the same thought.
- Derek Parnell (22/60) Jun 11 2007 ... and that is a problem that no one can ever solve, right?
- Jascha Wetzel (8/14) Jun 12 2007 If these issues can only be solved through experiments, why not
- Roberto Mariottini (6/23) Jun 12 2007 [...]
- Georg Wrede (7/44) Jun 12 2007 I think parameter passing is a world separate from "other const or
- BCS (7/14) Jun 12 2007 The issue is that a and b in this code are of different types if T is a ...
- Georg Wrede (6/22) Jun 12 2007 (Disclaimer: I've been out of town some, so I might have missed
- Bill Baxter (22/47) Jun 12 2007 I think the big trouble here comes just from having const at all, not
- Georg Wrede (68/124) Jun 13 2007 Suppose we consider a function to be a soap bubble. Variables declared
- eao197 (29/40) Jun 13 2007 That all is already in C++:
- Don Clugston (8/55) Jun 13 2007 It's worse than that. You can call any global function, or any static fu...
- eao197 (6/16) Jun 13 2007 But why trying to transform D to a functional language instead of use on...
- sambeau (Sam Phillips) (7/9) Jun 13 2007
- Bent Rasmussen (17/35) Jun 13 2007 The nice thing about D is that it is a multi paradigm language*, but in
- OF (6/23) Jun 13 2007 I've actually been thinking about exactly this (pure functions in D) and...
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (7/42) Jun 13 2007 D has CTFE which allows execution of "pure functions" at compile time. A...
- Georg Wrede (14/17) Jun 13 2007 The day D gets purely functional, I'm outta here!
- Falk Henrich (7/17) Jun 13 2007 I totally agree. Functional concepts like HOF etc. are nice while
- Deewiant (12/54) Jun 14 2007 Pure functions would need to be limited in more ways than that. Here's s...
- Bruno Medeiros (6/18) Jun 11 2007 Will using tuples to declare function parameters allow us to declare
- Bruno Medeiros (5/25) Jun 11 2007 --
- Bent Rasmussen (2/2) Jun 10 2007 const-by-default. That is just my feeling. But I'm sure there is a well
- Carlos Santander (5/25) Jun 10 2007 I vote 2 because of having safety as default. Plus, it would only be a t...
- Thomas Kuehne (24/30) Jun 10 2007 -----BEGIN PGP SIGNED MESSAGE-----
- Frank Benoit (4/4) Jun 10 2007 I have lots of D code. And i would be happy to spend a week to constify
- gareis (6/20) Jun 10 2007 Doubt it makes much difference, but I prefer having function arguments
- Jeff Nowakowski (8/9) Jun 10 2007 Option 2, and I'll quote Walter:
- Leandro Lucarella (12/13) Jun 11 2007 --
- Charlie (6/26) Jun 10 2007 2 gets my vote!
- Daniel Giddings (3/13) Jun 10 2007 One more vote for const by default here. With C++ programming, having to...
- Rioshin an'Harthen (8/17) Jun 11 2007 I'd definitely go for option 2 - having had to code const correct C++, I...
- torhu (6/14) Jun 11 2007 'var' is shorter than 'mutable', so that might be a good option for a
- eao197 (37/40) Jun 11 2007 ch.
- Stephen Waits (12/12) Jun 11 2007 I vote 2: const-by-default. But this needs a LOT more thinking.
- Robert Fraser (3/23) Jun 11 2007 I'm rather against the whole constness concept in general, but I think b...
- Myron Alexander (10/10) Jun 11 2007 My coding style screams 'const by default' but Walter raises some
- Ary Manzana (16/36) Jun 11 2007 2) const by default.
- Dan (3/3) Jun 12 2007 Another option is to not allow a default, and make everyone explicitly d...
- Craig Black (8/8) Jun 12 2007 I prefer const-by-default for function parameters. More often than not,...
- Robert Fraser (2/7) Jun 12 2007 I don't like this idea at all. Both "default" ways would only break some...
- Bent Rasmussen (11/17) Jun 12 2007 I don't see var as pointless; in global scope it's optional; in function...
- Georg Wrede (10/15) Jun 12 2007 Most definitely 2.
- sambeau (Sam Phillips) (7/11) Jun 12 2007
- Sean Kelly (9/18) Jun 12 2007 I'd like to at least try option 2. It sounds appealing in theory, but
- Jarrett Billingsley (4/11) Jun 12 2007 Oh absolutely. CbD kind of implies a "non-default" case where it wouldn...
- Lars Ivar Igesund (7/25) Jun 12 2007 I'd like to try 2)
- kris (6/24) Jun 12 2007 ++ for option 2
- Daniel Keep (20/20) Jun 12 2007 I want to see option #2, but I think more work needs to be done to
- Bill Baxter (41/68) Jun 12 2007 In the world of const though, really what you want is for that to become
- Reiner Pope (2/4) Jun 12 2007 I'd like to try this one.
- nobody nowhere.nonet (4/14) Jun 14 2007 Option 2 is definitely better.
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
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
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
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
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
Less typing AND safer in the end? It is a no brainer. 2
Jun 10 2007
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
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
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 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.) 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 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
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
Walter Bright wrote:Bill Baxter wrote: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* "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
Bill Baxter wrote:Walter Bright wrote:I agree with your example, although I would think it makes sense to put 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).Bill Baxter wrote: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.* "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.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
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
Bill Baxter wrote:Walter Bright wrote: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.Bill Baxter wrote: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.* "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
Walter Bright wrote:Bill Baxter wrote: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.Walter Bright wrote: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.Bill Baxter wrote: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.* "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 11 2007
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
Reply to Walter,Don Clugston wrote: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){...}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.
Jun 11 2007
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
On Mon, 11 Jun 2007 12:11:40 -0700, Walter Bright wrote:Don Clugston wrote:So how do we find out the answer to that?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.... and that is a problem that no one can ever solve, right?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);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.parnellThe 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.
Jun 11 2007
Walter Bright wrote:Don Clugston wrote: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.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.
Jun 12 2007
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
Walter Bright wrote:Bill Baxter wrote:True. See below.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.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 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.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.
Jun 12 2007
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
BCS wrote:Reply to Georg,(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 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
Georg Wrede wrote:BCS wrote: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. --bbReply to Georg,(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 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
Bill Baxter wrote:Georg Wrede wrote: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.BCS wrote: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.Reply to Georg,(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 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 13 2007
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
eao197 wrote:On Wed, 13 Jun 2007 16:13:01 +0400, Georg Wrede <georg nospam.org> wrote: <...skipped...>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.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.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.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.
Jun 13 2007
On Wed, 13 Jun 2007 17:30:27 +0400, Don Clugston <dac nospam.com.au> wrote:But why trying to transform D to a functional language instead of use one of such languages? -- Regards, Yauheni AkhotnikauAnd 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.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.
Jun 13 2007
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
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:But why trying to transform D to a functional language instead of use one of such languages? -- Regards, Yauheni AkhotnikauAnd 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.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.
Jun 13 2007
Georg Wrede Wrote: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.I've actually been thinking about exactly this (pure functions in D) and can't let this pass without giving it support. Pure functions are great for both bug fighting reasons and optimizations. Knowing that a function doesn't have any side effects at all means that it can not be the source of "weird" bugs, and it means that it can run concurrently. That it has the same return value for any given input is nice for optimizations -- one could even implement dynamic programming generation in the compiler (though I can't say I'd suggest that for D), and if the input is constant pure functions can always be run at compile time. Those that haven't used pure functional or even just functional languages might not appreciate the simplifications pure functions brings, but it makes very much sense to use on "real" functions (like mathematical functions, as compared to procedures/subroutines). It might be beyond the intended scope of D, but a simple pure attribute for pure functions would be very nice and could be beneficial. I can see the problems with enforcing it though, without restricting pointer and perhaps gc use. Just my point of view.
Jun 13 2007
OF wrote:Georg Wrede Wrote:D has CTFE which allows execution of "pure functions" at compile time. Also using functions as compile time generators doesn't imply they can't have side effects. It's just a design decision.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.I've actually been thinking about exactly this (pure functions in D) and can't let this pass without giving it support. Pure functions are great for both bug fighting reasons and optimizations. Knowing that a function doesn't have any side effects at all means that it can not be the source of "weird" bugs, and it means that it can run concurrently. That it has the same return value for any given input is nice for optimizations -- one could even implement dynamic programming generation in the compiler (though I can't say I'd suggest that for D), and if the input is constant pure functions can always be run at compile time.Those that haven't used pure functional or even just functional languages might not appreciate the simplifications pure functions brings, but it makes very much sense to use on "real" functions (like mathematical functions, as compared to procedures/subroutines).I don't believe D is going to be purely functional anywhere in the near future. There was only talk about constness of e.g. function parameters and certain variables.
Jun 13 2007
Jari-Matti Mäkelä wrote:I don't believe D is going to be purely functional anywhere in the near future. There was only talk about constness of e.g. function parameters and certain variables.The day D gets purely functional, I'm outta here! But, several aspects that relate to recognizing functions as purely functional or not, do give us both immediate benefits as well as open up avenues for significant gains in the future. A language that handles (and understands) smoothly both functional and non-functional code, is in a position to reap the benefits from both worlds. This is no more peculiar than the fact that D is an excellent language for both OO and non-OO programming, as well as mixed OO/non-OO programming. We are already using pure functions (like sin(x), abs(x), etc.) in our code, and this does not have to become any more complicated than that. But for the compiler, optimizer, parallel code generator, and some other future things, knowing which functions are Pure, is simply essential.
Jun 13 2007
Georg Wrede wrote:The day D gets purely functional, I'm outta here!So am I.A language that handles (and understands) smoothly both functional and non-functional code, is in a position to reap the benefits from both worlds. This is no more peculiar than the fact that D is an excellent language for both OO and non-OO programming, as well as mixed OO/non-OO programming.I totally agree. Functional concepts like HOF etc. are nice while input/output tends to be messy in functional languages. So why not incorporate the good stuff and avoid the practically unusable parts?We are already using pure functions (like sin(x), abs(x), etc.) in our code, and this does not have to become any more complicated than that. But for the compiler, optimizer, parallel code generator, and some other future things, knowing which functions are Pure, is simply essential.Absolutely correct! Falk
Jun 13 2007
OF wrote:Georg Wrede Wrote:Pure functions would need to be limited in more ways than that. Here's some stuff beyond pointers and the heap which pure functions can't mess with: - static variables, - impure functions, - any state (non-const variables) defined outside the function. I actually just took these from my original post on the issue (Message-ID is e014er$22rn$1 digitaldaemon.com, it can also be found at http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=35852). That was in the context of templates, with Hasan Aljudy asking for CTFE, but pure functions are IMHO notably more useful. It's a handy compile-time contract and leads to a lot of optimization opportunities.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.I've actually been thinking about exactly this (pure functions in D) and can't let this pass without giving it support. Pure functions are great for both bug fighting reasons and optimizations. Knowing that a function doesn't have any side effects at all means that it can not be the source of "weird" bugs, and it means that it can run concurrently. That it has the same return value for any given input is nice for optimizations -- one could even implement dynamic programming generation in the compiler (though I can't say I'd suggest that for D), and if the input is constant pure functions can always be run at compile time. Those that haven't used pure functional or even just functional languages might not appreciate the simplifications pure functions brings, but it makes very much sense to use on "real" functions (like mathematical functions, as compared to procedures/subroutines). It might be beyond the intended scope of D, but a simple pure attribute for pure functions would be very nice and could be beneficial. I can see the problems with enforcing it though, without restricting pointer and perhaps gc use. Just my point of view.
Jun 14 2007
Walter Bright wrote:Bill Baxter wrote: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* "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 11 2007
Bruno Medeiros wrote:Walter Bright wrote:Nevermind, seems you already confirmed that in another post:Bill Baxter wrote:Will using tuples to declare function parameters allow us to declare ref/inout parameters?* "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.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
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
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
-----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
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
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
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
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
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
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
"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
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
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=ch. I vote for this.2) Parameters are const-by-default, and must be marked mutable otherwi=se.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
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
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
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
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
Another option is to not allow a default, and make everyone explicitly define the storage class of their data; just like they have to specify the type explicitly. Once that's in order, letting "auto" handle both type and storage class automatically unless otherwise specified might work? Just my three pennies (inflation).
Jun 12 2007
I prefer const-by-default for function parameters. More often than not, parameters should be const, so it makes sense to make them const by default. I think the argument against const by default is that it is not orthogonal because function parameters would require a different syntax than other variable declarations. I disagree with that argument because I think function parameters are different enough from other kinds of variable declarations to justify a different syntax. -Craig
Jun 12 2007
Dan Wrote:Another option is to not allow a default, and make everyone explicitly define the storage class of their data; just like they have to specify the type explicitly. Once that's in order, letting "auto" handle both type and storage class automatically unless otherwise specified might work? Just my three pennies (inflation).I don't like this idea at all. Both "default" ways would only break some existing code, this would break all existing code. In addition, it just seems needlessly verbose, and I'm sure I'm not the only one who hates having to type a pointless "var" in front variables in JavaScript or "my" in strict Perl (I know this would be for parameters, but it's the same general idea).
Jun 12 2007
I don't like this idea at all. Both "default" ways would only break some existing code, this would break all existing code. In addition, it just seems needlessly verbose, and I'm sure I'm not the only one who hates having to type aI agree.pointless "var" in front variables in JavaScript or "my" in strict Perl (I know this would be for parameters, but it's the same general idea).I don't see var as pointless; in global scope it's optional; in function scope it depends on whether you want it to be local or not. It's certainly but with type-inference and probably some support in Visual Studio to show show inferred types. That, coupled with intellisense, should be a nice productivity boost. An all-const approach with var for mutables would be interesting, if feasible... It reminds me of Single Assignment C (SAC), although I've never tried that. Bent
Jun 12 2007
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
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.</lurk> As far as I am concerned 2 is the only thing that makes sense. Parameters are not variables as far as I am concerned. Variables should, of course, be 'variable' by default. More functional and functional-style programming awaits us if we clearly mark our side effects... </lurk>
Jun 12 2007
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
"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
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
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
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
Daniel Keep wrote: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. -- DanielIn 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
Jarrett Billingsley wrote:2) Parameters are const-by-default, and must be marked mutable otherwise. Locals, fields etc. are still mutable by default.I'd like to try this one.
Jun 12 2007
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