digitalmars.D - const / readonly - a little honesty, please
- Matthew (94/94) Mar 09 2005 Just wanted to give a counter to Walter's recent const propaganda.
- Kris (9/103) Mar 09 2005 Does the compiler also complain if you assign an explicit more than once...
- Matthew (10/23) Mar 09 2005 Very good point.
- xs0 (14/49) Mar 09 2005 Well, as far as Java goes, if you declare something as final, you need
- Regan Heath (16/150) Mar 09 2005 Doesn't 'final' (in those languages) require that the variable be given ...
- Carlos Santander B. (7/28) Mar 09 2005 I also always thought that "final" in Java was a replacement for "const"...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (6/57) Mar 09 2005 And it actually does give an error similar to what you describe:
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (17/52) Mar 09 2005 I think "const" in the meaning of "readonly" could help with the
- Matthew (7/61) Mar 09 2005 Most certainly this issue needs to be resolved. I have no clear idea
- xs0 (23/108) Mar 10 2005 How about
- Charlie Patterson (11/22) Mar 10 2005 I personally like const, even when flawed. However your example sounds
-
Lynn Allan
(7/10)
Mar 10 2005
- Matthew (8/18) Mar 10 2005 Hmmm. I could give several answers, but since I've been somewhat
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (12/14) Mar 11 2005 Note:
- Derek Parnell (33/56) Mar 11 2005 Agreed.
- Ben Hinkle (7/19) Mar 11 2005 The compiler/lint can give a warning when a char[], wchar[] or dchar[] "...
- Derek Parnell (23/43) Mar 11 2005 But how would one tell the lint that my code is intentionally *not* doin...
- Ben Hinkle (8/36) Mar 11 2005 That's why it's a warning - and given that the standard is cow it would ...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (32/54) Mar 11 2005 If "readonly" is the default for arrays, then we would need some kind of
Just wanted to give a counter to Walter's recent const propaganda. const in C++ is an incredibly useful tool, and can be used - both in its intended/designed way, and in unforeseen ways - as a very powerful compile-time design enforcement mechanism. For anyone willing to brave all 628 pages, I discuss many of these in Imperfect C++. Sure, it has its flaws. No-one pretends that that's not so. Indeed, my latest "Flexible C++" instalment, called "Beware Logical Constness" (http://www.cuj.com/documents/cujexp0502wilson/), discusses how logical constness + multithreading is a dangerous combination. What Walter seems never to acknowledge with C++, or, at best, to couch in terms of irrelevance, is that const is (or at least has become) primarily important for communicating design constraints. Almost without exception, I couldn't give a flying fig whether the compiler puts my const variables in ROM, nor whether the compiler is prevented from making certain optimisations for fear of my constness being logical and not physical. I value const as a design enforcement mechanism. And, for that purpose, I have a hard time not considering anyone who stipulates it to be valueless as either dishonest or ignorant, because it is so manifestly demonstrable to be extremely useful. Let me lay out what I think is the crucial difference between mine and Walter's positions, and why you should all be wary of believing either of us to be 100% correct on this subject. Walter is first and foremost a compiler writer, and as such he sees const as a flawed idea because of (i) the fact that it is useless for optimisation, and (ii) it adds a lot of complexity. He (apparently) couldn't care less about its usefulness in helping the compiler to enforce the programmer's design. I am first and foremost a library writer, and as such see const to be a *hugely* successful idea because (i) it allows me to express highly important semantics to the users of my code, and (ii) it allows me to protect my code against misuse. I (admittedly) couldn't give a stuff about its ROMifications, and am largely unconcerned by the ability to subvert physical constness for logical constness (though I remain mindful of the dangers therein when I need to; hence the recent "Flexible C++" instalment mentioned above.) Now, what I've recently asked for is a small, specific subset of C++'s const, namely in the enforcement of explicit instantiation of members. This has got NOTHING to do with truely const things that can go in ROM. It has got NOTHING to do with any type of physical / logical const subversion. And, unless I'm a complete moron, it will add VERY LITTLE complexity into the compiler. But what it _will_ do is prevent errors of omission in the initialisation of the members of types in non-trivial constructors, and thereby make D a better language than it currently is for producing robust code. (That'd be a good thing, no?). And do you know how I know this to be true, rather than just conjecture and pro-const propaganda? Because I made precisely that error of omission in the writing of Database.this() in std.openrj!! If it helps people keep away from all the irrelevant arguments I've covered above, let's call it the 'explicit' keyword. It would be used as in the following example: class X { public this(int i) { y = i; z = 1; } // y == i, z == 1 this(long i) { z = 1; } // y == 0, z == 1 this(short s) { y = s; } // COMPILE ERROR: explicit member 'z' not explicitly initialised private: int y; explicit int z; } Now, please please please can we have on-point opinions on this particular facet of C++'s multifaceted const facility? I challenge anyone to demonstrate how having this facility will not be a manifest improvement in code correctness. (Note: adding the 'explicit' keyword will not be a waste at all. I have several other plans for it, the seeds of which may be found dotted throughout Imperfect C++ <g> ...) -- Matthew Wilson Author: "Imperfect C++", Addison-Wesley, 2004 (http://www.imperfectcplusplus.com) Contributing editor, C/C++ Users Journal (http://www.synesis.com.au/articles.html#columns) Director, Synesis Software (www.synesis.com.au) STLSoft moderator (http://www.stlsoft.org) Synesis Software Pty Ltd P.O.Box 125 Waverley New South Wales, 2024 Australia -----------------------------------------------------
Mar 09 2005
Does the compiler also complain if you assign an explicit more than once? If so, then this could be considered similar to 'final' variables in other languages. I've often found a need for the latter in D (particularly with singletons), and had to fudge it through various means. If this is not the same thing, then I'd like to ask for a 'final' ... in /addition/ to what you're describing. They are related, and they do catch implementation errors at compile-time. - Kris In article <d0nua5$di5$1 digitaldaemon.com>, Matthew says...Just wanted to give a counter to Walter's recent const propaganda. const in C++ is an incredibly useful tool, and can be used - both in its intended/designed way, and in unforeseen ways - as a very powerful compile-time design enforcement mechanism. For anyone willing to brave all 628 pages, I discuss many of these in Imperfect C++. Sure, it has its flaws. No-one pretends that that's not so. Indeed, my latest "Flexible C++" instalment, called "Beware Logical Constness" (http://www.cuj.com/documents/cujexp0502wilson/), discusses how logical constness + multithreading is a dangerous combination. What Walter seems never to acknowledge with C++, or, at best, to couch in terms of irrelevance, is that const is (or at least has become) primarily important for communicating design constraints. Almost without exception, I couldn't give a flying fig whether the compiler puts my const variables in ROM, nor whether the compiler is prevented from making certain optimisations for fear of my constness being logical and not physical. I value const as a design enforcement mechanism. And, for that purpose, I have a hard time not considering anyone who stipulates it to be valueless as either dishonest or ignorant, because it is so manifestly demonstrable to be extremely useful. Let me lay out what I think is the crucial difference between mine and Walter's positions, and why you should all be wary of believing either of us to be 100% correct on this subject. Walter is first and foremost a compiler writer, and as such he sees const as a flawed idea because of (i) the fact that it is useless for optimisation, and (ii) it adds a lot of complexity. He (apparently) couldn't care less about its usefulness in helping the compiler to enforce the programmer's design. I am first and foremost a library writer, and as such see const to be a *hugely* successful idea because (i) it allows me to express highly important semantics to the users of my code, and (ii) it allows me to protect my code against misuse. I (admittedly) couldn't give a stuff about its ROMifications, and am largely unconcerned by the ability to subvert physical constness for logical constness (though I remain mindful of the dangers therein when I need to; hence the recent "Flexible C++" instalment mentioned above.) Now, what I've recently asked for is a small, specific subset of C++'s const, namely in the enforcement of explicit instantiation of members. This has got NOTHING to do with truely const things that can go in ROM. It has got NOTHING to do with any type of physical / logical const subversion. And, unless I'm a complete moron, it will add VERY LITTLE complexity into the compiler. But what it _will_ do is prevent errors of omission in the initialisation of the members of types in non-trivial constructors, and thereby make D a better language than it currently is for producing robust code. (That'd be a good thing, no?). And do you know how I know this to be true, rather than just conjecture and pro-const propaganda? Because I made precisely that error of omission in the writing of Database.this() in std.openrj!! If it helps people keep away from all the irrelevant arguments I've covered above, let's call it the 'explicit' keyword. It would be used as in the following example: class X { public this(int i) { y = i; z = 1; } // y == i, z == 1 this(long i) { z = 1; } // y == 0, z == 1 this(short s) { y = s; } // COMPILE ERROR: explicit member 'z' not explicitly initialised private: int y; explicit int z; } Now, please please please can we have on-point opinions on this particular facet of C++'s multifaceted const facility? I challenge anyone to demonstrate how having this facility will not be a manifest improvement in code correctness. (Note: adding the 'explicit' keyword will not be a waste at all. I have several other plans for it, the seeds of which may be found dotted throughout Imperfect C++ <g> ...) -- Matthew Wilson Author: "Imperfect C++", Addison-Wesley, 2004 (http://www.imperfectcplusplus.com) Contributing editor, C/C++ Users Journal (http://www.synesis.com.au/articles.html#columns) Director, Synesis Software (www.synesis.com.au) STLSoft moderator (http://www.stlsoft.org) Synesis Software Pty Ltd P.O.Box 125 Waverley New South Wales, 2024 Australia -----------------------------------------------------
Mar 09 2005
"Kris" <Kris_member pathlink.com> wrote in message news:d0nvsl$fn7$1 digitaldaemon.com...Does the compiler also complain if you assign an explicit more than once? If so, then this could be considered similar to 'final' variables in other languages. I've often found a need for the latter in D (particularly with singletons), and had to fudge it through various means. If this is not the same thing, then I'd like to ask for a 'final' ... in /addition/ to what you're describing. They are related, and they do catch implementation errors at compile-time. - KrisVery good point. Being as how I prefer to make the decisions when it comes to writing my code, I'd maybe suggest that we can have permutations of int x; explict int x; final int x; explicit final int x; But that may be deemed overly complex.
Mar 09 2005
Well, as far as Java goes, if you declare something as final, you need to set it in all constructors (if it's not already set within the declaration). If a constructor calls another constructor that initializes it, it's also fine.. If there is no constructor, it's an invalid class, if a constructor doesn't initialize it, it's an invalid constructor. So this is not exactly what you'd like (because it includes the var being a constant), but I guess there are few cases where you'd both like to definitely initialize something and to also have it changeable (because if it's not final, you can simply uninitialize it later, so you again have no guarantee), so perhaps a solution is to simply adopt those final semantics (it would also make Java people switching to D happier :). xs0 Matthew wrote:"Kris" <Kris_member pathlink.com> wrote in message news:d0nvsl$fn7$1 digitaldaemon.com...Does the compiler also complain if you assign an explicit more than once? If so, then this could be considered similar to 'final' variables in other languages. I've often found a need for the latter in D (particularly with singletons), and had to fudge it through various means. If this is not the same thing, then I'd like to ask for a 'final' ... in /addition/ to what you're describing. They are related, and they do catch implementation errors at compile-time. - KrisVery good point. Being as how I prefer to make the decisions when it comes to writing my code, I'd maybe suggest that we can have permutations of int x; explict int x; final int x; explicit final int x; But that may be deemed overly complex.
Mar 09 2005
On Wed, 9 Mar 2005 23:12:22 +0000 (UTC), Kris <Kris_member pathlink.com> wrote:Does the compiler also complain if you assign an explicit more than once? If so, then this could be considered similar to 'final' variables in other languages. I've often found a need for the latter in D (particularly with singletons), and had to fudge it through various means. If this is not the same thing, then I'd like to ask for a 'final' ... in /addition/ to what you're describing. They are related, and they do catch implementation errors at compile-time.Doesn't 'final' (in those languages) require that the variable be given a value where it's declared i.e. class A { final int a = 5; } of course we could diverge from this and allow class A { final int a; this() { a = 5; //omit this and get an error. } } which is what Matthew is after. Regan- Kris In article <d0nua5$di5$1 digitaldaemon.com>, Matthew says...Just wanted to give a counter to Walter's recent const propaganda. const in C++ is an incredibly useful tool, and can be used - both in its intended/designed way, and in unforeseen ways - as a very powerful compile-time design enforcement mechanism. For anyone willing to brave all 628 pages, I discuss many of these in Imperfect C++. Sure, it has its flaws. No-one pretends that that's not so. Indeed, my latest "Flexible C++" instalment, called "Beware Logical Constness" (http://www.cuj.com/documents/cujexp0502wilson/), discusses how logical constness + multithreading is a dangerous combination. What Walter seems never to acknowledge with C++, or, at best, to couch in terms of irrelevance, is that const is (or at least has become) primarily important for communicating design constraints. Almost without exception, I couldn't give a flying fig whether the compiler puts my const variables in ROM, nor whether the compiler is prevented from making certain optimisations for fear of my constness being logical and not physical. I value const as a design enforcement mechanism. And, for that purpose, I have a hard time not considering anyone who stipulates it to be valueless as either dishonest or ignorant, because it is so manifestly demonstrable to be extremely useful. Let me lay out what I think is the crucial difference between mine and Walter's positions, and why you should all be wary of believing either of us to be 100% correct on this subject. Walter is first and foremost a compiler writer, and as such he sees const as a flawed idea because of (i) the fact that it is useless for optimisation, and (ii) it adds a lot of complexity. He (apparently) couldn't care less about its usefulness in helping the compiler to enforce the programmer's design. I am first and foremost a library writer, and as such see const to be a *hugely* successful idea because (i) it allows me to express highly important semantics to the users of my code, and (ii) it allows me to protect my code against misuse. I (admittedly) couldn't give a stuff about its ROMifications, and am largely unconcerned by the ability to subvert physical constness for logical constness (though I remain mindful of the dangers therein when I need to; hence the recent "Flexible C++" instalment mentioned above.) Now, what I've recently asked for is a small, specific subset of C++'s const, namely in the enforcement of explicit instantiation of members. This has got NOTHING to do with truely const things that can go in ROM. It has got NOTHING to do with any type of physical / logical const subversion. And, unless I'm a complete moron, it will add VERY LITTLE complexity into the compiler. But what it _will_ do is prevent errors of omission in the initialisation of the members of types in non-trivial constructors, and thereby make D a better language than it currently is for producing robust code. (That'd be a good thing, no?). And do you know how I know this to be true, rather than just conjecture and pro-const propaganda? Because I made precisely that error of omission in the writing of Database.this() in std.openrj!! If it helps people keep away from all the irrelevant arguments I've covered above, let's call it the 'explicit' keyword. It would be used as in the following example: class X { public this(int i) { y = i; z = 1; } // y == i, z == 1 this(long i) { z = 1; } // y == 0, z == 1 this(short s) { y = s; } // COMPILE ERROR: explicit member 'z' not explicitly initialised private: int y; explicit int z; } Now, please please please can we have on-point opinions on this particular facet of C++'s multifaceted const facility? I challenge anyone to demonstrate how having this facility will not be a manifest improvement in code correctness. (Note: adding the 'explicit' keyword will not be a waste at all. I have several other plans for it, the seeds of which may be found dotted throughout Imperfect C++ <g> ...) -- Matthew Wilson Author: "Imperfect C++", Addison-Wesley, 2004 (http://www.imperfectcplusplus.com) Contributing editor, C/C++ Users Journal (http://www.synesis.com.au/articles.html#columns) Director, Synesis Software (www.synesis.com.au) STLSoft moderator (http://www.stlsoft.org) Synesis Software Pty Ltd P.O.Box 125 Waverley New South Wales, 2024 Australia -----------------------------------------------------
Mar 09 2005
Regan Heath wrote:Doesn't 'final' (in those languages) require that the variable be given a value where it's declared i.e. class A { final int a = 5; }I also always thought that "final" in Java was a replacement for "const" (besides meaning not virtual).of course we could diverge from this and allow class A { final int a; this() { a = 5; //omit this and get an error. } } which is what Matthew is after.Right now, "final" isn't documented (AFAIK), so I think that's a reasonable idea (I mean, it's not like it's set in stone what it does).Regan_______________________ Carlos Santander Bernal
Mar 09 2005
Matthew wrote:If it helps people keep away from all the irrelevant arguments I've covered above, let's call it the 'explicit' keyword. It would be used as in the following example: class X { public this(int i) { y = i; z = 1; } // y == i, z == 1 this(long i) { z = 1; } // y == 0, z == 1 this(short s) { y = s; } // COMPILE ERROR: explicit member 'z' not explicitly initialised private: int y; explicit int z; }This sounds a lot like how "final" works in Java:class X { public X (int i) { y = i; z = 1; } // y == i, z == 1 public X (long i) { z = 1; } // y == 0, z == 1 public X (char s) { y = s; } // COMPILE ERROR: explicit member 'z' not explicitly initialised private int y; private final int z; }And it actually does give an error similar to what you describe:*** Semantic Error: The blank final field "z" must be initialized in this and every constructor which does not call a form of this(); or else once in an instance initializer block or instance field initializer.BTW; I normally use Jikes for compiling my Java (doesn't everyone ?) Javac says a more boring: "variable z might not have been initialized" --anders
Mar 09 2005
Matthew wrote:Almost without exception, I couldn't give a flying fig whether the compiler puts my const variables in ROM, nor whether the compiler is prevented from making certain optimisations for fear of my constness being logical and not physical. I value const as a design enforcement mechanism. And, for that purpose, I have a hard time not considering anyone who stipulates it to be valueless as either dishonest or ignorant, because it is so manifestly demonstrable to be extremely useful.I think "const" in the meaning of "readonly" could help with the string literals blowing up in your face when you assign to them ? (not happening on Windows, unless the compiler uses string pooling) Like this change in a certain C++ compiler: http://msdn.microsoft.com/library/en-us/vclang/html/ vclrfstringliteralshavepropertypeofconstchar%5B%5D.aspString literals now have the type const char [] and are now placed in a read-only section of memory. Changing that memory will now cause an access violation. Code compiled in previous versions using /GF will also cause the access violation.It could also help with "remembering" to use Copy-on-Write ? Like in C++ terms:#define READONLY const char *upperstr(READONLY char *str) { // Copy-on-Write char *copy = strdup(str); assert(copy != NULL); return upperstr(copy); } char *upperstr(char *str) { int i, len; len = strlen(str); for (i = 0; i < len; i++) { char c = str[i]; str[i] = toupper(c); } return str; }So that it would use the correct version, with string literals ? With D, there's no difference between the two routines - except that the bottom one forgets to .dup, and thus can't handle ""... It might even help people to stay off the toString() value ? Little things like that. Name it "readonly" if const is bad... Some suggested using "in" vs. "out" here, but that would apply to the value of str - right? (as in the pointer, not the chars) --anders
Mar 09 2005
Most certainly this issue needs to be resolved. I have no clear idea how, and suspect that it needs the wisdom and insight of big-W to come up with the solution. One thing I do know: all operating systems should have identical behaviour in this regard. "Anders F Björklund" <afb algonet.se> wrote in message news:d0o1p4$hf5$1 digitaldaemon.com...Matthew wrote:Almost without exception, I couldn't give a flying fig whether the compiler puts my const variables in ROM, nor whether the compiler is prevented from making certain optimisations for fear of my constness being logical and not physical. I value const as a design enforcement mechanism. And, for that purpose, I have a hard time not considering anyone who stipulates it to be valueless as either dishonest or ignorant, because it is so manifestly demonstrable to be extremely useful.I think "const" in the meaning of "readonly" could help with the string literals blowing up in your face when you assign to them ? (not happening on Windows, unless the compiler uses string pooling) Like this change in a certain C++ compiler: http://msdn.microsoft.com/library/en-us/vclang/html/ vclrfstringliteralshavepropertypeofconstchar%5B%5D.aspString literals now have the type const char [] and are now placed in a read-only section of memory. Changing that memory will now cause an access violation. Code compiled in previous versions using /GF will also cause the access violation.It could also help with "remembering" to use Copy-on-Write ? Like in C++ terms:#define READONLY const char *upperstr(READONLY char *str) { // Copy-on-Write char *copy = strdup(str); assert(copy != NULL); return upperstr(copy); } char *upperstr(char *str) { int i, len; len = strlen(str); for (i = 0; i < len; i++) { char c = str[i]; str[i] = toupper(c); } return str; }So that it would use the correct version, with string literals ? With D, there's no difference between the two routines - except that the bottom one forgets to .dup, and thus can't handle ""... It might even help people to stay off the toString() value ? Little things like that. Name it "readonly" if const is bad... Some suggested using "in" vs. "out" here, but that would apply to the value of str - right? (as in the pointer, not the chars) --anders
Mar 09 2005
How about func(int[in] arr); // I won't touch the contents func(int[inout] arr); // I may, same as the default func(int[out] arr); // I won't read them, but will write The last one is different from "out int[]" because it still gets the length and allocated memory, and is useful for declaring that the contents of the array don't influence the result. Then there's the fun with func(out int[in] arr); // illegal, can't have read-only to null :) func(out int[inout] arr); // illegal, can't read from null func(out int[out] arr); // the [out] has no effect, so prolly illegal // too func(inout int[in] arr); // I won't touch the original array, // but may return a different one (cool // when the original is sliced somewhere // else) (CoW, basically) func(inout int[inout] arr); // I may do anything func(inout int[out] arr); // I may reuse the array or not (perhaps // to avoid reallocation), but I don't // care about its contents Thoughts? xs0 Matthew wrote:Most certainly this issue needs to be resolved. I have no clear idea how, and suspect that it needs the wisdom and insight of big-W to come up with the solution. One thing I do know: all operating systems should have identical behaviour in this regard. "Anders F Björklund" <afb algonet.se> wrote in message news:d0o1p4$hf5$1 digitaldaemon.com...Matthew wrote:Almost without exception, I couldn't give a flying fig whether the compiler puts my const variables in ROM, nor whether the compiler is prevented from making certain optimisations for fear of my constness being logical and not physical. I value const as a design enforcement mechanism. And, for that purpose, I have a hard time not considering anyone who stipulates it to be valueless as either dishonest or ignorant, because it is so manifestly demonstrable to be extremely useful.I think "const" in the meaning of "readonly" could help with the string literals blowing up in your face when you assign to them ? (not happening on Windows, unless the compiler uses string pooling) Like this change in a certain C++ compiler: http://msdn.microsoft.com/library/en-us/vclang/html/ vclrfstringliteralshavepropertypeofconstchar%5B%5D.aspString literals now have the type const char [] and are now placed in a read-only section of memory. Changing that memory will now cause an access violation. Code compiled in previous versions using /GF will also cause the access violation.It could also help with "remembering" to use Copy-on-Write ? Like in C++ terms:#define READONLY const char *upperstr(READONLY char *str) { // Copy-on-Write char *copy = strdup(str); assert(copy != NULL); return upperstr(copy); } char *upperstr(char *str) { int i, len; len = strlen(str); for (i = 0; i < len; i++) { char c = str[i]; str[i] = toupper(c); } return str; }So that it would use the correct version, with string literals ? With D, there's no difference between the two routines - except that the bottom one forgets to .dup, and thus can't handle ""... It might even help people to stay off the toString() value ? Little things like that. Name it "readonly" if const is bad... Some suggested using "in" vs. "out" here, but that would apply to the value of str - right? (as in the pointer, not the chars) --anders
Mar 10 2005
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:d0nua5$di5$1 digitaldaemon.com...class X { public this(short s) { y = s; } // COMPILE ERROR: explicit member 'z' not explicitly initialised private: int y; explicit int z; }I personally like const, even when flawed. However your example sounds trivial. As a library writer you want to make sure that any variable you have gone out of your way to mark 'explicit' then cries foul in your *own* constructors if not set. Sure it might save a bug or two, but it's not much. Libraries get vetted quickly enough. The app writer using your libraries doesn't get squat for all this. Or as you point out, there is no semantics passed up. While I'm not used to in, out, inout, and I don't like looking at them, they seem to cover your point about semantics.
Mar 10 2005
I am first and foremost a library writer, and as such see const tobe a*hugely* successful idea because (i) it allows me to express highly important semantics to the users of my code<alert comment="newbie who may not understand the issues"> Seems like your advocated usage of "const" for library routines can be more or less accomplished with "in" parameters? The "consumer" of your library wouldn't/shouldn't care about other variables that are presumably hidden/private. </alert>
Mar 10 2005
"Lynn Allan" <l_d_allan adelphia.net> wrote in message news:d0rd7c$128k$1 digitaldaemon.com...Hmmm. I could give several answers, but since I've been somewhat snappish/boorish lately, I'll conjure a nice one <g>: "I am flattered that you obviously assume that library writers are infallible, but unfortunately they're not. Therefore, they are (almost) as much in need of assistance from compilers as 'normal' programmers." That ok? :-)I am first and foremost a library writer, and as such see const tobe a*hugely* successful idea because (i) it allows me to express highly important semantics to the users of my code<alert comment="newbie who may not understand the issues"> Seems like your advocated usage of "const" for library routines can be more or less accomplished with "in" parameters? The "consumer" of your library wouldn't/shouldn't care about other variables that are presumably hidden/private. </alert>
Mar 10 2005
Lynn Allan wrote:Seems like your advocated usage of "const" for library routines can be more or less accomplished with "in" parameters?Note: All parameters are "in", unless declared as "out" or "inout"... The only way that this could apply to, say char[] parameters, if if they were "extended" to something like "char[out]" or so ? Currently "in" only applies to the array (or pointer) itself, and *not* to the actual characters that it is referencing. The D language at the moment treats all parameters as readonly, and suggests using the Copy-on-Write 'idiom'. But does not enforce it. It's a little like with the implicit cast of "bar[]" into "bar*", it can be convenient and less typing, and it can also hide bugs ? --anders
Mar 11 2005
On Fri, 11 Mar 2005 09:22:55 +0100, Anders F Björklund wrote:Lynn Allan wrote:Agreed. The Copy-on-Write idiom being suggested by Walter, places the responsibility of preserving the referred-to data on the writer of the routine being called. In other words, if one is writing a routine, and that routine can receive reference parameters that are 'in' types, eg. char[], or Class instances, etc...), the one is expected to take a copy of the referred-to data *if* one is going to modify it (for any reason). Except if the *purpose* of the routine is to modify the referred-to data /in place/. For example, a ToUpperCase() routine might have been designed to change the string in situ. Or it might have been designed to return an modified string but leave the original intact. However, because one can never be certain that the routine writer has used this idiom, it is 'safer' to pass a reference to a copy of the data instead of a reference to the original data. It would be nice if we could get the compiler to help us error prone coders. If would just tell the compiler that my intention is to *not* change some referred-to data, then the compiler could alert me to code that actually is known to change the data. This alone would be a great advance in being able to express the coder's intentions and thus reduce mistakes in source code. I do understand that there are some cases in which the compiler cannot detect that some referred-to data will actually be changed, but I'm happy to live with that because that is exactly what we have now. However, there are times when the compiler *can* detect unintentional attempts to alter 'preserved' data. Please notice that I have not used the keyword 'const' in the above discussion. That terminology is obvious overloaded, and I hoped instead to just talk in plain simple English. -- Derek Parnell Melbourne, Australia 11/03/2005 11:12:39 PMSeems like your advocated usage of "const" for library routines can be more or less accomplished with "in" parameters?Note: All parameters are "in", unless declared as "out" or "inout"... The only way that this could apply to, say char[] parameters, if if they were "extended" to something like "char[out]" or so ? Currently "in" only applies to the array (or pointer) itself, and *not* to the actual characters that it is referencing. The D language at the moment treats all parameters as readonly, and suggests using the Copy-on-Write 'idiom'. But does not enforce it. It's a little like with the implicit cast of "bar[]" into "bar*", it can be convenient and less typing, and it can also hide bugs ? --anders
Mar 11 2005
[snip]However, because one can never be certain that the routine writer has used this idiom, it is 'safer' to pass a reference to a copy of the data instead of a reference to the original data. It would be nice if we could get the compiler to help us error prone coders. If would just tell the compiler that my intention is to *not* change some referred-to data, then the compiler could alert me to code that actually is known to change the data. This alone would be a great advance in being able to express the coder's intentions and thus reduce mistakes in source code.The compiler/lint can give a warning when a char[], wchar[] or dchar[] "in" parameter is modified in place. The warning would say "modifying string input parameter - possible violation of copy-on-write". They would then search around for copy-on-write in the doc and learn about the "right" way. [snip] -Ben
Mar 11 2005
On Fri, 11 Mar 2005 07:48:55 -0500, Ben Hinkle wrote:[snip]But how would one tell the lint that my code is intentionally *not* doing a copy-on-write? As in the ToUpperCase() example. // Modify in place - i.e. Not CoW. dchar[] ToUpperCase(dchar[] x) { foreach(inout dchar c; x) c = Upper(c); return x; } // Return a new modified string - i.e. CoW dchar[] ToUpperCase(dchar[] x) { dchar[] y; y.length = x.length; foreach(int i, inout dchar c; x) y[i] = Upper(c); return y; } -- Derek Parnell Melbourne, Australia 11/03/2005 11:49:35 PMHowever, because one can never be certain that the routine writer has used this idiom, it is 'safer' to pass a reference to a copy of the data instead of a reference to the original data. It would be nice if we could get the compiler to help us error prone coders. If would just tell the compiler that my intention is to *not* change some referred-to data, then the compiler could alert me to code that actually is known to change the data. This alone would be a great advance in being able to express the coder's intentions and thus reduce mistakes in source code.The compiler/lint can give a warning when a char[], wchar[] or dchar[] "in" parameter is modified in place. The warning would say "modifying string input parameter - possible violation of copy-on-write". They would then search around for copy-on-write in the doc and learn about the "right" way.
Mar 11 2005
"Derek Parnell" <derek psych.ward> wrote in message news:1scvmsoj94p35$.1jlrqgw7ijhz2.dlg 40tude.net...On Fri, 11 Mar 2005 07:48:55 -0500, Ben Hinkle wrote:That's why it's a warning - and given that the standard is cow it would be odd to write a large number of functions that violate cow since users who expect cow (like me) would get confused about how to use those functions. One could also mark the input to ToUpperCase as inout, which would have the effect of forcing it to be an lvalue but has the benefit of informing users and the compiler/lint of the intention.[snip]But how would one tell the lint that my code is intentionally *not* doing a copy-on-write? As in the ToUpperCase() example.However, because one can never be certain that the routine writer has used this idiom, it is 'safer' to pass a reference to a copy of the data instead of a reference to the original data. It would be nice if we could get the compiler to help us error prone coders. If would just tell the compiler that my intention is to *not* change some referred-to data, then the compiler could alert me to code that actually is known to change the data. This alone would be a great advance in being able to express the coder's intentions and thus reduce mistakes in source code.The compiler/lint can give a warning when a char[], wchar[] or dchar[] "in" parameter is modified in place. The warning would say "modifying string input parameter - possible violation of copy-on-write". They would then search around for copy-on-write in the doc and learn about the "right" way.
Mar 11 2005
Derek Parnell wrote:But how would one tell the lint that my code is intentionally *not* doing a copy-on-write?If "readonly" is the default for arrays, then we would need some kind of keyword telling that the array in question would be modified in place. One suggestion that came up was to use the "in" and "out" keywords, as in: "dchar[in]" (which would be the default) and "dchar[inout]" In C and C++, there in-place read-write is the default and you use the oddly named "const" keyword to tell that it's a read-only: const char* It could be made to work similar in D, just make read-only the default ? Easier than changing everything else to use "readonly char[]" arguments. It would also make Object.toString() make more sense, as it would return a readonly string and not a writable buffer tino the objects innards...As in the ToUpperCase() example. // Modify in place - i.e. Not CoW. dchar[] ToUpperCase(dchar[] x) { foreach(inout dchar c; x) c = Upper(c); return x; }This could use some keyword telling that it will *not* follow the standard idiom of using copy-on-write, but will modify in place... (which would also mean that it would segfault if passed a literal!) Something like: dchar[] ToUpperCase(dchar[inout] x); or dchar[] ToUpperCase(readwrite dchar[] x); Placing "out" before the array: dchar[] ToUpperCase(out dchar[] x); Just means that you will modify the *slice* (i.e. like length or ptr), not that you mean to change the actual characters that it points to... (the very ones it was currently pointing to on function entry, that is) Examples: void read(out char[] s); This means that it will read from the stread into a new buffer, and then return a slice to this buffer. But *not* that it will change the characters that s was pointing to, when the function was called.// Return a new modified string - i.e. CoW dchar[] ToUpperCase(dchar[] x) { dchar[] y; y.length = x.length; foreach(int i, inout dchar c; x) y[i] = Upper(c); return y; }You might want to look at std.string.toupper, for the default routine ? (taking the default string type, char[], as a Copy-on-Write argument, and optimized both for ASCII strings and for "already uppercase" too) --anders
Mar 11 2005