www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Stepping back and looking at constness from another angle.

reply Regan Heath <regan netmail.co.nz> writes:
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
next sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
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
parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
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
parent reply Regan Heath <regan netmail.co.nz> writes:
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
next sibling parent Xinok <xnknet gmail.com> writes:
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
prev sibling next sibling parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
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
parent Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
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
prev sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
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
parent Regan Heath <regan netmail.co.nz> writes:
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
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
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
parent Regan Heath <regan netmail.co.nz> writes:
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