digitalmars.D - Re: Stepping back and looking at constness from another angle.
- Regan Heath <regan netmail.co.nz> Jun 07 2007
- Lionello Lunesu <lio lunesu.remove.com> Jun 08 2007
- Deewiant <deewiant.doesnotlike.spam gmail.com> Jun 08 2007
- Regan Heath <regan netmail.co.nz> Jun 08 2007
- Xinok <xnknet gmail.com> Jun 08 2007
- Deewiant <deewiant.doesnotlike.spam gmail.com> Jun 08 2007
- Deewiant <deewiant.doesnotlike.spam gmail.com> Jun 08 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jun 08 2007
- Regan Heath <regan netmail.co.nz> Jun 08 2007
- Derek Parnell <derek psych.ward> Jun 08 2007
- Regan Heath <regan netmail.co.nz> Jun 08 2007
Denton Cockburn Wrote:On Thu, 07 Jun 2007 16:25:21 +1000, Reiner Pope wrote:Another problem with const by default came to mind. Consider the following code, with const-not-by-default: void foo( ref const(char)[] c) { c = c[1..$]; } I would hate to see this in const-by-default, which would try to wrap a const( ) around the whole type. To counter that, you would probably have to write some mess like void foo ( mutable( ref const(char)[] ) c ) { c = c[1..$]; } -- Reiner
Again, I'm also trying to understand this, knowing that things change a lot over the course of the discussion. That being said, I thought the current position is that by adding any other qualifier, such as ref, const/scope/final is no longer automatically applied.
I thought so too. As Don says; 'ref' is an alias of 'inout'. It's ver y purpose is to indicate a variable which is going to be modified. Therefore it stands to reason that function parameters passed as 'ref' will be mutable by default. :) Regan
Jun 07 2007
Regan Heath wrote:Denton Cockburn Wrote:Again, I'm also trying to understand this, knowing that things change a lot over the course of the discussion. That being said, I thought the current position is that by adding any other qualifier, such as ref, const/scope/final is no longer automatically applied.
I thought so too. As Don says; 'ref' is an alias of 'inout'. It's ver y purpose is to indicate a variable which is going to be modified. Therefore it stands to reason that function parameters passed as 'ref' will be mutable by default. :)
Actually, it might be a nice distinction to keep both 'inout' and 'ref', where 'inout' would be mutable, but 'ref' not? 'ref' would then be an optimized version of 'in'. Or will 'inout' disappear completely? L.
Jun 08 2007
Lionello Lunesu wrote:Regan Heath wrote:As Don says; 'ref' is an alias of 'inout'. It's ver y purpose is to indicate a variable which is going to be modified. Therefore it stands to reason that function parameters passed as 'ref' will be mutable by default. :)
Actually, it might be a nice distinction to keep both 'inout' and 'ref', where 'inout' would be mutable, but 'ref' not? 'ref' would then be an optimized version of 'in'. Or will 'inout' disappear completely?
'ref' meaning what C++'s 'const foo&' is how I originally understood it, but from all the discussion I've gathered that 'inout' will be deprecated and then phased out after all. So 'ref' will be only the new name for 'inout'. I hope I'm wrong, I think 'inout' is more self-documenting than 'ref'. -- Remove ".doesnotlike.spam" from the mail address.
Jun 08 2007
Deewiant Wrote:Lionello Lunesu wrote:Regan Heath wrote:As Don says; 'ref' is an alias of 'inout'. It's ver y purpose is to indicate a variable which is going to be modified. Therefore it stands to reason that function parameters passed as 'ref' will be mutable by default. :)
Actually, it might be a nice distinction to keep both 'inout' and 'ref', where 'inout' would be mutable, but 'ref' not? 'ref' would then be an optimized version of 'in'. Or will 'inout' disappear completely?
'ref' meaning what C++'s 'const foo&' is how I originally understood it, but from all the discussion I've gathered that 'inout' will be deprecated and then phased out after all. So 'ref' will be only the new name for 'inout'. I hope I'm wrong, I think 'inout' is more self-documenting than 'ref'.
I liked 'inout' better than 'ref' too. I was against the initial proposal before I left for 6 months and when I got back, there it was! 'inout' was originally intended to signal the intent of the function to "read from the parameter and write back to it". Much like 'out' just meant "I will only write to this" and the default 'in' meant "I will only read this". 'ref' however is an instruction to pass by reference, which is a whole other kettle of fish. Yes, 'inout' has to pass by reference in order to carry out it's intention but that doesn't make it the same thing. My original argument against adding anything more to the language was something along the lines of.. If you want to pass something by reference, why not pass a pointer to it. After all, in D, you can dereference a pointer in exactly the same way as you would the thing itself, eg. struct A { int member; } void foo(A a) { a.member = 5; } void foo(A* a) { a.member = 5; } notice that to dereference a struct passed by value, or a pointer to a struct you always use '.' That said, the call site would look like foo(&a); instead of the cleaner foo(a)... which is perhaps why C++ added a pass-by-reference & to be used in place of the pointer * syntax. Hmm.. idea; why not allow foo(a) and automatically convert to foo(&a) internally if 'a' is not a pointer. I mean, the compiler knows what 'a' is, it knows what 'foo' wants, why can't we have the syntax automatically, much like we do for dereferencing. Regan
Jun 08 2007
Main reason I can think of is function overloading. This is an acceptable overload: void foo(A a) void foo(A* a) And if you allow 'a' to automatically convert to '&a': foo(a); // Ambiguous error Regan Heath wrote:Hmm.. idea; why not allow foo(a) and automatically convert to foo(&a) internally if 'a' is not a pointer. I mean, the compiler knows what 'a' is, it knows what 'foo' wants, why can't we have the syntax automatically, much like we do for dereferencing. Regan
Jun 08 2007
Regan Heath wrote:Deewiant Wrote:'ref' meaning what C++'s 'const foo&' is how I originally understood it, but from all the discussion I've gathered that 'inout' will be deprecated and then phased out after all. So 'ref' will be only the new name for 'inout'. I hope I'm wrong, I think 'inout' is more self-documenting than 'ref'.
I liked 'inout' better than 'ref' too. I was against the initial proposal before I left for 6 months and when I got back, there it was! 'inout' was originally intended to signal the intent of the function to "read from the parameter and write back to it". Much like 'out' just meant "I will only write to this" and the default 'in' meant "I will only read this". 'ref' however is an instruction to pass by reference, which is a whole other kettle of fish. Yes, 'inout' has to pass by reference in order to carry out it's intention but that doesn't make it the same thing. My original argument against adding anything more to the language was something along the lines of.. If you want to pass something by reference, why not pass a pointer to it. After all, in D, you can dereference a pointer in exactly the same way as you would the thing itself, eg. struct A { int member; } void foo(A a) { a.member = 5; } void foo(A* a) { a.member = 5; } notice that to dereference a struct passed by value, or a pointer to a struct you always use '.' That said, the call site would look like foo(&a); instead of the cleaner foo(a)... which is perhaps why C++ added a pass-by-reference & to be used in place of the pointer * syntax. Hmm.. idea; why not allow foo(a) and automatically convert to foo(&a) internally if 'a' is not a pointer. I mean, the compiler knows what 'a' is, it knows what 'foo' wants, why can't we have the syntax automatically, much like we do for dereferencing.
We'd lose the ability to overload a function with both foo(A) and foo(A*), but to be honest I can't think of a use case for that anyway. I like it! We could lose 'ref' completely. -- Remove ".doesnotlike.spam" from the mail address.
Jun 08 2007
Deewiant wrote:Regan Heath wrote:Hmm.. idea; why not allow foo(a) and automatically convert to foo(&a) internally if 'a' is not a pointer. I mean, the compiler knows what 'a' is, it knows what 'foo' wants, why can't we have the syntax automatically, much like we do for dereferencing.
We'd lose the ability to overload a function with both foo(A) and foo(A*), but to be honest I can't think of a use case for that anyway. I like it! We could lose 'ref' completely.
Didn't take long to come up with a case: bool contains(char[] string, char character); bool contains(char[] string, char* cstring); bool contains(char[] string, char[] string2); With first-class arrays I'd say this isn't a big problem, and I'd say the handiness of your idea is worth the minor hassle of having to pass cstring to a toString function, but it's something to consider. -- Remove ".doesnotlike.spam" from the mail address.
Jun 08 2007
Regan Heath wrote:Deewiant Wrote:Lionello Lunesu wrote:
struct A { int member; } void foo(A a) { a.member = 5; } void foo(A* a) { a.member = 5; } notice that to dereference a struct passed by value, or a pointer to a struct you always use '.' That said, the call site would look like foo(&a); instead of the cleaner foo(a)... which is perhaps why C++ added a pass-by-reference & to be used in place of the pointer * syntax. Hmm.. idea; why not allow foo(a) and automatically convert to foo(&a) internally if 'a' is not a pointer. I mean, the compiler knows what 'a' is, it knows what 'foo' wants, why can't we have the syntax automatically, much like we do for dereferencing.
Good idea. I'd be perfectly happy to do that with structs. Now that you mention it, it is kind of inconsistent that D basically turns astruct.foo into (&astruct).foo for you, but it wont turn foo(astruct) into foo(&astruct) for you. (Here assuming the D meaning of '.' is like C++ '->') But how do you handle overloads on '*'? void foo(int x) { /* sets foo to x */ } void foo(int* x) { /* returns foo via x*/ } I guess that's already impossible with inout anyway. We get along currently just fine without being able to overload on inout, so maybe the loss of overload on '*' would go mostly unnoticed? I think this feature should be limited to one level, though. Calling a 'void foo(int **x)' with a plain int is probably not going to do what the user expects. --bb
Jun 08 2007
Bill Baxter Wrote:Regan Heath wrote:Deewiant Wrote:Lionello Lunesu wrote:
struct A { int member; } void foo(A a) { a.member = 5; } void foo(A* a) { a.member = 5; } notice that to dereference a struct passed by value, or a pointer to a struct you always use '.' That said, the call site would look like foo(&a); instead of the cleaner foo(a)... which is perhaps why C++ added a pass-by-reference & to be used in place of the pointer * syntax. Hmm.. idea; why not allow foo(a) and automatically convert to foo(&a) internally if 'a' is not a pointer. I mean, the compiler knows what 'a' is, it knows what 'foo' wants, why can't we have the syntax automatically, much like we do for dereferencing.
Good idea. I'd be perfectly happy to do that with structs. Now that you mention it, it is kind of inconsistent that D basically turns astruct.foo into (&astruct).foo for you, but it wont turn foo(astruct) into foo(&astruct) for you. (Here assuming the D meaning of '.' is like C++ '->') But how do you handle overloads on '*'? void foo(int x) { /* sets foo to x */ } void foo(int* x) { /* returns foo via x*/ } I guess that's already impossible with inout anyway. We get along currently just fine without being able to overload on inout, so maybe the loss of overload on '*' would go mostly unnoticed? I think this feature should be limited to one level, though. Calling a 'void foo(int **x)' with a plain int is probably not going to do what the user expects.
True, but calling with an int* should be allowed? I'm wondering if that would be ok or just confusing... not sure. Regan
Jun 08 2007
On Thu, 07 Jun 2007 18:42:03 -0400, Regan Heath wrote:Denton Cockburn Wrote:On Thu, 07 Jun 2007 16:25:21 +1000, Reiner Pope wrote:Another problem with const by default came to mind. Consider the following code, with const-not-by-default: void foo( ref const(char)[] c) { c = c[1..$]; } I would hate to see this in const-by-default, which would try to wrap a const( ) around the whole type. To counter that, you would probably have to write some mess like void foo ( mutable( ref const(char)[] ) c ) { c = c[1..$]; } -- Reiner
Again, I'm also trying to understand this, knowing that things change a lot over the course of the discussion. That being said, I thought the current position is that by adding any other qualifier, such as ref, const/scope/final is no longer automatically applied.
I thought so too. As Don says; 'ref' is an alias of 'inout'. It's ver y purpose is to indicate a variable which is going to be modified. Therefore it stands to reason that function parameters passed as 'ref' will be mutable by default. :) Regan
I have to disagree Regan. 'ref' might mean that the passing mechanism is "by reference" but it does not necessarily mean that the access permission is 'allowed to change". Do not get parameter passing mechanics confused with access permissions. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
Jun 08 2007
Derek Parnell Wrote:On Thu, 07 Jun 2007 18:42:03 -0400, Regan Heath wrote:Denton Cockburn Wrote:On Thu, 07 Jun 2007 16:25:21 +1000, Reiner Pope wrote:Another problem with const by default came to mind. Consider the following code, with const-not-by-default: void foo( ref const(char)[] c) { c = c[1..$]; } I would hate to see this in const-by-default, which would try to wrap a const( ) around the whole type. To counter that, you would probably have to write some mess like void foo ( mutable( ref const(char)[] ) c ) { c = c[1..$]; } -- Reiner
Again, I'm also trying to understand this, knowing that things change a lot over the course of the discussion. That being said, I thought the current position is that by adding any other qualifier, such as ref, const/scope/final is no longer automatically applied.
I thought so too. As Don says; 'ref' is an alias of 'inout'. It's ver y purpose is to indicate a variable which is going to be modified. Therefore it stands to reason that function parameters passed as 'ref' will be mutable by default. :) Regan
I have to disagree Regan. 'ref' might mean that the passing mechanism is "by reference" but it does not necessarily mean that the access permission is 'allowed to change". Do not get parameter passing mechanics confused with access permissions.
You're dead right. In fact 'ref' (a passing mechanic) is/has replaced 'inout' (signifying 'this reference is allowed to change') so it seems Walter/D is confusing the two. Regan
Jun 08 2007