www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - My thoughts & tries with rvalue references

reply "Namespace" <rswhite4 googlemail.com> writes:
Hey guys,
I would like to show you my tries and thoughts about rvalue 
references and their syntax.
As discussed in my other thread in the learn group 
(http://forum.dlang.org/thread/uswucstsooghescofycp forum.dlang.org?page=2#post-mailman.294.1364252397.4724.digitalmars-d-lea
n:40puremagic.com), 
auto ref is not longer an option for non-template functions.
Because of that I learned to read the compiler code and start my 
own tries, as you can read in my thread also 
(http://forum.dlang.org/thread/uswucstsooghescofycp forum.dlang.org?page=3#post-jrksuqqremsqgicmybri:40forum.dlang.org).
One of my tries was a kind of pseudo-property " ref" and finally 
a hybrid of D and C++: ref&.
Because I think a property isn't the best solution, I like to 
hear your thougths about my idea with "ref&".
Here a small example:

void bar1(ref& A a) { } // OK
void bar2(ref &A a) { } // OK
void bar21(&A a) { } // Error: '&' can only be used in 
combination with 'ref'.
void bar22(& A a) { } // Error: '&' can only be used in 
combination with 'ref'.
void bar3(ref const& A a) { } // OK
void bar4(ref const &A a) { } // OK
void bar5(ref &const A a) { } // Error: '&' Must be directly used 
in front of the type.
void bar6(ref& const A a) { } // Error: '&' Must be directly used 
in front of the type.

And for templates:

void foo(T)(ref &T t) { }

As you can see, '&' can only be used in front of the type and 
cannot exist without 'ref'.

The advantages of this syntax would be:
  - it is short
  - It is easy to implement
  - it is known from C++
  - It does not cause conflicts with other things
and it is (IMO) a very nice hybrid of C++ ref and D ref.

Hope you like it, just like me. But I would like to hear your 
general opinions about it.
Thanks in advance.
Mar 29 2013
parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Friday, 29 March 2013 at 13:45:48 UTC, Namespace wrote:
 Hey guys,
 I would like to show you my tries and thoughts about rvalue 
 references and their syntax.
 As discussed in my other thread in the learn group 
 (http://forum.dlang.org/thread/uswucstsooghescofycp forum.dlang.org?page=2#post-mailman.294.1364252397.4724.digitalmars-d-lea
n:40puremagic.com), 
 auto ref is not longer an option for non-template functions.
 Because of that I learned to read the compiler code and start 
 my own tries, as you can read in my thread also 
 (http://forum.dlang.org/thread/uswucstsooghescofycp forum.dlang.org?page=3#post-jrksuqqremsqgicmybri:40forum.dlang.org).
 One of my tries was a kind of pseudo-property " ref" and 
 finally a hybrid of D and C++: ref&.
 Because I think a property isn't the best solution, I like to 
 hear your thougths about my idea with "ref&".
 Here a small example:

 void bar1(ref& A a) { } // OK
 void bar2(ref &A a) { } // OK
 void bar21(&A a) { } // Error: '&' can only be used in 
 combination with 'ref'.
 void bar22(& A a) { } // Error: '&' can only be used in 
 combination with 'ref'.
 void bar3(ref const& A a) { } // OK
 void bar4(ref const &A a) { } // OK
 void bar5(ref &const A a) { } // Error: '&' Must be directly 
 used in front of the type.
 void bar6(ref& const A a) { } // Error: '&' Must be directly 
 used in front of the type.

 And for templates:

 void foo(T)(ref &T t) { }

 As you can see, '&' can only be used in front of the type and 
 cannot exist without 'ref'.

 The advantages of this syntax would be:
   - it is short
   - It is easy to implement
   - it is known from C++
   - It does not cause conflicts with other things
 and it is (IMO) a very nice hybrid of C++ ref and D ref.

 Hope you like it, just like me. But I would like to hear your 
 general opinions about it.
 Thanks in advance.
The major downside is that if you don't come from C++ it's hard to understand why 'ref &' means what you propose. The major upsides are, as you mention, it's very concise and perfectly intuitive if you DO come from C++. In the spirit of trying to come up with something for comparison, the best attribute I've thought of so far is ' val': void bar1( val ref A a) { } The advantage is that it's consistent with my understanding of the general approach to adding things to D at this point. But that's also it's disadvantage: it's nothing more than a mundane attribute.
Mar 29 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 The major downside is that if you don't come from C++ it's hard 
 to understand why 'ref &' means what you propose. The major 
 upsides are, as you mention, it's very concise and perfectly 
 intuitive if you DO come from C++. In the spirit of trying to 
 come up with something for comparison, the best attribute I've 
 thought of so far is ' val':

 void bar1( val ref A a) { }

 The advantage is that it's consistent with my understanding of 
 the general approach to adding things to D at this point. But 
 that's also it's disadvantage: it's nothing more than a mundane 
 attribute.
Yes you're right. But I just think that a property does not make sense here, because we mix then two different things: storage classes and properties. This strikes me as wrong. When I implemented the pseudo-property ref, I realized this. It seemed inconsistent compared to the rest of the D syntax. And since D, syntactically as well as linguistically (D provides direct access to C / C++), is a descendant of C++, I'd prefer to take a kind of hybrid: ref&. And to pull the reverse: Why should ' val ref' be more intuitive than ref&? Or why should be ' ref' more intuitive? What I mean by that: Both the Property as well as the hybrid path have their weaknesses and are not necessarily immediately obvious. But we should choose one of them and focus on this so that somebody can make a pull request for it.
Mar 30 2013
next sibling parent reply "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
On Saturday, 30 March 2013 at 09:17:17 UTC, Namespace wrote:
 And to pull the reverse: Why should ' val ref' be more 
 intuitive than ref&? Or why should be ' ref' more intuitive?
 What I mean by that:
 Both the Property as well as the hybrid path have their 
 weaknesses and are not necessarily immediately obvious. But we 
 should choose one of them and focus on this so that somebody 
 can make a pull request for it.
Because & in C++ means "by ref". D has "ref" for that. So ref& doesn't make sense. One might think it as a double reference(?)
Mar 30 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
 Because & in C++ means "by ref".
 D has "ref" for that.

 So ref& doesn't make sense. One might think it as a double 
 reference(?)
You are undermining my authority. :P I choose ref& because it is a hybrid of the C++ ref style and D's ref style. That's what I said in my first post. And C++ has const& for that kind of problem. In C++ it means that it accept both, rvalues and lvalues, but in D not. So we shouldn't be that fussy. ;) Do you like ' ref' more? Or have you another idea? I could imagine that '&A' (without ref) would work too, but I think that the most of you will say "It's too cryptic. It's C++ style.". I opened this thread in the first place to get at all other opinions or ideas. And possibly that we might find a common solution that I would try to implement. So let's hear.
Mar 30 2013
parent "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
Personally yes, I prefer  ref more. But you are right that it's 
not nice to be an annotation.
Mar 30 2013
prev sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 30.03.2013 11:12, schrieb Minas Mina:
 On Saturday, 30 March 2013 at 09:17:17 UTC, Namespace wrote:
 And to pull the reverse: Why should ' val ref' be more intuitive than
 ref&? Or why should be ' ref' more intuitive?
 What I mean by that:
 Both the Property as well as the hybrid path have their weaknesses and
 are not necessarily immediately obvious. But we should choose one of
 them and focus on this so that somebody can make a pull request for it.
Because & in C++ means "by ref". D has "ref" for that. So ref& doesn't make sense. One might think it as a double reference(?)
I have to agree on that. My first impression was that ref& is equal to c++11 && Kind Regards Benjamin Thaut
Mar 30 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 I have to agree on that. My first impression was that ref& is 
 equal to c++11 &&

 Kind Regards
 Benjamin Thaut
Ok, it seems that I think differently. And what is the general opinion of '&A' instead of 'ref &A'? It has all the benefits that I described in my first post, but it may not be so confusing. If you like to ask "why not A&": That is more complex as it seems to be, a opinion which is shared by Jonathan. And I sincerely hope that no one is annoyed about my attempts to solve this problem.
Mar 30 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
As far as I studied the code, something like  ref isn't possible, 
because ref is already a keyword. Except as Pseudo-property. But 
this is a combination of ' ' and 'ref' so that both, ' ref' and 
'  ref' would be valid.
I still like the idea of '&A'.
Mar 30 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Saturday, 30 March 2013 at 12:00:32 UTC, Namespace wrote:
 As far as I studied the code, something like  ref isn't 
 possible, because ref is already a keyword. Except as 
 Pseudo-property. But this is a combination of ' ' and 'ref' so 
 that both, ' ref' and '  ref' would be valid.
 I still like the idea of '&A'.
I have to disagree with me here. Thanks to this thread (http://forum.dlang.org/thread/ohjdraaizvwiczifwrlk forum.dlang.org) I know now that after the ' ' can be an unlimited number of white spaces. Hence my previous speculation that I would have implemented something wrong is wrong. So is something like ' ref' possible and already implemented, as you can see here: https://github.com/Dgame/dmd/tree/rvalue_property I think this is probably the end result of my little journey. Any objections? Quick example: [code] struct A { public: ubyte id; this(ubyte id) { this.id = id; } this(this) { } } void foo( ref A a) { writeln(":: id = ", a.id); } void foo1( ref const A a) { writeln(":: id = ", a.id); } void foo2( ref shared A a) { writeln(":: id = ", a.id); } void foo3( ref immutable A a) { writeln(":: id = ", a.id); } // void foo4( ref lazy A a) { /// Error: incompatible parameter storage classes // writeln(":: id = ", a.id); // } // void foo5( ref ref A a) { /// Error: redundant storage class ref // writeln(":: id = ", a.id); // } // void foo6( ref out A a) { /// Error: incompatible parameter storage classes // writeln(":: id = ", a.id); // } void bar( ref int a) { writeln(a); } void quatz(T)( ref T t) { static if (is(T == struct)) writeln(t.id); else writeln(t); } [/code]
Apr 02 2013
parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Tuesday, 2 April 2013 at 15:08:20 UTC, Namespace wrote:
 On Saturday, 30 March 2013 at 12:00:32 UTC, Namespace wrote:
 As far as I studied the code, something like  ref isn't 
 possible, because ref is already a keyword. Except as 
 Pseudo-property. But this is a combination of ' ' and 'ref' so 
 that both, ' ref' and '  ref' would be valid.
 I still like the idea of '&A'.
I have to disagree with me here. Thanks to this thread (http://forum.dlang.org/thread/ohjdraaizvwiczifwrlk forum.dlang.org) I know now that after the ' ' can be an unlimited number of white spaces. Hence my previous speculation that I would have implemented something wrong is wrong. So is something like ' ref' possible and already implemented, as you can see here: https://github.com/Dgame/dmd/tree/rvalue_property I think this is probably the end result of my little journey. Any objections?
' ref' is actually my least favorite choice. Of all presented, my two favorites are void func(ref& int a) {} void func( val ref int a) {} Hara Kenji's comment about 'scope ref' also raises the issue of just how subtle is the difference between this proposed feature and what 'auto ref' does in templates. Correct me if I'm wrong, but 'ref&' is proposed to have the compiler create a temporary at the call site and pass it as a reference. ref int func1(ref& int a) { return a; } // Example: int func2(ref int b) { return a; } int x = func2(func1(3)); The above passes because the temporary ref to "3" created for func1 survives the whole expression, I believe. func1 returns the 3 as a ref, which ref should not escape the original expression, but may escape func1 itself. So 'scope ref' cannot be used. 'scope ref' *could* be used for the related "performance ref" issue, wherein the compiler decides whether a ref or value is appropriate knowing full well there's no chance of escaping. There are actually three ref issues here. The performance ref issue is related to the compiler making automatic choices which have no affect on semantics. The other two issues are related to the Don't Repeat Yourself problem. 'auto ref' is the template solution which actually creates new functions depending on what is passed to it. The alternative solution is what's being proposed here, which I'll call the 'temp ref' solution. Instead of passing values to a custom created function, all rvalues are simply converted to temporary lvalues at the call site, with the caller responsible for tracking the value's scope. It might seem convenient to use the syntax 'auto ref' to tell a non-templated function to do this, but that syntax has been rejected for reasons I either never understood well enough or I've simply forgotten. All-in-all, the syntax 'ref &' seems harmless enough to me. As far as getting it to work with templates, the feature is clearly mutually exclusive with 'auto ref', but I'm not sure why any other usage would be a problem.
Apr 02 2013
next sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Wednesday, 3 April 2013 at 01:19:18 UTC, Zach the Mystic wrote:
 On Tuesday, 2 April 2013 at 15:08:20 UTC, Namespace wrote:
 On Saturday, 30 March 2013 at 12:00:32 UTC, Namespace wrote:
 As far as I studied the code, something like  ref isn't 
 possible, because ref is already a keyword. Except as 
 Pseudo-property. But this is a combination of ' ' and 'ref' 
 so that both, ' ref' and '  ref' would be valid.
 I still like the idea of '&A'.
I have to disagree with me here. Thanks to this thread (http://forum.dlang.org/thread/ohjdraaizvwiczifwrlk forum.dlang.org) I know now that after the ' ' can be an unlimited number of white spaces. Hence my previous speculation that I would have implemented something wrong is wrong. So is something like ' ref' possible and already implemented, as you can see here: https://github.com/Dgame/dmd/tree/rvalue_property I think this is probably the end result of my little journey. Any objections?
' ref' is actually my least favorite choice. Of all presented, my two favorites are void func(ref& int a) {} void func( val ref int a) {} Hara Kenji's comment about 'scope ref' also raises the issue of just how subtle is the difference between this proposed feature and what 'auto ref' does in templates. Correct me if I'm wrong, but 'ref&' is proposed to have the compiler create a temporary at the call site and pass it as a reference. ref int func1(ref& int a) { return a; } // Example: int func2(ref int b) { return a; } int x = func2(func1(3));
s/ref int b/ref int a/
Apr 02 2013
prev sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
 It might seem convenient to use the syntax 'auto ref' to tell a 
 non-templated function to do this, but that syntax has been 
 rejected for reasons I either never understood well enough or 
 I've simply forgotten.
In my first post I link to Jonathan response to this.
 All-in-all, the syntax 'ref &' seems harmless enough to me. As 
 far as getting it to work with templates, the feature is 
 clearly mutually exclusive with 'auto ref', but I'm not sure 
 why any other usage would be a problem.
I like 'ref&' also, but the reaction seemed to imply that it looks not like a temp ref, more like a double ref. So we came back to ' ref'. And in terms of 'scope ref': scope works currently only for delegates so you could customize the behavior of scope ref quite appropriately. 'scope ref' is my second favorite alternative. The ranking would be: 1. ref& 2. scope ref / ref in 3. ref For all of these a proposal and a finished implementation of mine is ready, you have to choose and to review only. :)
Apr 02 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
It would interest me which of the suggestions would be rather 
accepted.
  - scope ref as Kenji suggested
  - Or rather  ref because this is the way that D usually goes 
when it comes to subsequent expansions.

What do you think?
Apr 03 2013
next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 3 April 2013 at 17:48:54 UTC, Namespace wrote:
 It would interest me which of the suggestions would be rather 
 accepted.
  - scope ref as Kenji suggested
  - Or rather  ref because this is the way that D usually goes 
 when it comes to subsequent expansions.

 What do you think?
I am against introducing new one-symbol meanings, it always looks like a hack. scope ref is much more elegant but I still can't get straight in my mind what this combination does mean from the abstract type system point of view.
Apr 03 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Wednesday, 3 April 2013 at 18:06:36 UTC, Dicebot wrote:
 On Wednesday, 3 April 2013 at 17:48:54 UTC, Namespace wrote:
 It would interest me which of the suggestions would be rather 
 accepted.
 - scope ref as Kenji suggested
 - Or rather  ref because this is the way that D usually goes 
 when it comes to subsequent expansions.

 What do you think?
I am against introducing new one-symbol meanings, it always looks like a hack. scope ref is much more elegant but I still can't get straight in my mind what this combination does mean from the abstract type system point of view.
So you were against the introduction of ravalue references or do you just have a problem with the syntax?
Apr 03 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 3 April 2013 at 20:22:10 UTC, Namespace wrote:
 So you were against the introduction of ravalue references or 
 do you just have a problem with the syntax?
I am against whole "ref" design in D and consider it a mistake :) But within current specification requirements - against "hacky" syntax, rvalue references are useful indeed.
Apr 04 2013
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 I am against introducing new one-symbol meanings, it always 
 looks like a hack. scope ref is much more elegant but I still 
 can't get straight in my mind what this combination does mean 
 from the abstract type system point of view.
Addendum to scope ref: It could mean: "This ref parameter accepts also rvalues​​, because no reference can leave the scope". Therefore it is safe to pass a rvalue by ref.
Apr 03 2013
prev sibling parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Wednesday, 3 April 2013 at 17:48:54 UTC, Namespace wrote:
 It would interest me which of the suggestions would be rather 
 accepted.
  - scope ref as Kenji suggested
  - Or rather  ref because this is the way that D usually goes 
 when it comes to subsequent expansions.

 What do you think?
I simply can't reconcile the stated intention of 'scope' parameters with this feature. And ' ref' really makes no sense to me, being even less intuitive than 'ref&'. My belief is that this feature carries with it an inherent frustration because the existing syntaxes can't accomodate it, each being just slightyl off the mark, and to add a whole new keyword or ' ' storage class seems like not getting too much reward for the convenience the feature provides. 'scope ref': The only existing documentation on scope parameters: http://dlang.org/function.html suggests that references to them simply cannot leave the function they find themselves in. But this is *not* what the temp ref feature is about. Say you have this temp ref function: ref int func( temp ref int a) { return a; } According to the spec, it clearly violates 'scope', but is nonetheless valid and safe, as far as I can tell. The compiler can easily track the scope of a given lvalue at the call site: static int* x; static int y; x = *func(3); // Error: result of func(3) is assumed to be local x = *func(y); // Pass: address of y is known to be global This kind of safety checking is not yet implemented, but is suggested in DIP25, http://wiki.dlang.org/DIP25 . I believe it is the right way to go. The locality of the return by reference is assumed to be as local as the reference which is passed into it. So the temp '3' reference would make the result of func(3) yield a local, barring any other information which would allow the compiler to safely assume otherwise. In essence, ' temp ref' can escape its scope safely because the locality of the result is not its responsibility. As far as the fact that the meaning of 'scope' is not yet set in stone and may change to adapt to new purposes, the question would be whether its current definition is useful enough as is without needing to expand it (rather counter-intuitively, to be honest) to mean something different. ' ref': I like this less than 'ref&' because it is even less clear what it means than 'ref&' is. The two problems with 'ref&', so far as I understand it, are 1, that it looks like a one-character hack which generally not well-liked in this community, and 2, it could be confused with a double-reference. I personally don't think I'm going to confuse 'ref&' with 'ref *'. At least 'ref&' gives a hint that it has something to do with taking the address of something. ' ref' is nothing more than saying, "Hey, I can take ' ' and put it before keyword 'ref'. Look at me!". I'm not for it at all. If 'ref&' or ' ref' are rejected on the basis of their being one-character hacks, then the search is on for a good ' ' word or an existing keyword which does the trick. I wish 'scope' could cover it, but I personally don't see how that keyword as defined covers this feature as proposed. I looked for other existing keywords to do the job, but I didn't find one which met my personal sense of what would work. 'auto ref' would have been a perfect name for it if 'auto ref' hadn't already found great use in templates. All I have, therefore, are ' val' and, given this post, ' temp': void func( val ref int a) {} void func( temp ref int a) {} I think ' val' is pretty good. I don't think this feature merits its own keyword, so the ' ' is there to stay, but at least ' val' is only four letters long, exactly the same number of characters as 'auto'. Does anyone else have a better ' ttribute' for this feature, assuming one-char hacks are out of the question?
Apr 03 2013
next sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Thursday, 4 April 2013 at 01:07:08 UTC, Zach the Mystic wrote:
 static int* x;
 static int y;
 x = *func(3); // Error: result of func(3) is assumed to be local
 x = *func(y); // Pass: address of y is known to be global
s/*func/&func/
Apr 03 2013
prev sibling next sibling parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Thursday, 4 April 2013 at 01:07:08 UTC, Zach the Mystic wrote:
 'scope ref': The only existing documentation on scope 
 parameters: http://dlang.org/function.html suggests that 
 references to them simply cannot leave the function they find 
 themselves in. But this is *not* what the temp ref feature is 
 about. Say you have this temp ref function:

 ref int func( temp ref int a) { return a; }

 According to the spec, it clearly violates 'scope', but is 
 nonetheless valid and safe, as far as I can tell. The compiler 
 can easily track the scope of a given lvalue at the call site:

 static int* x;
 static int y;
 x = *func(3); // Error: result of func(3) is assumed to be local
 x = *func(y); // Pass: address of y is known to be global

 This kind of safety checking is not yet implemented, but is 
 suggested in DIP25, http://wiki.dlang.org/DIP25 . I believe it 
 is the right way to go. The locality of the return by reference 
 is assumed to be as local as the reference which is passed into 
 it. So the temp '3' reference would make the result of func(3) 
 yield a local, barring any other information which would allow 
 the compiler to safely assume otherwise. In essence, ' temp 
 ref' can escape its scope safely because the locality of the 
 result is not its responsibility.
On the other hand, a ' temp ref' parameter *should* be prevented from being assigned directly to a global, since it might be stack-allocated: static int* x; void func( temp ref int a) { x = &a; // Error, 'a' might be stack-allocated } This *would* be an acceptable error. It's completely unsafe to assume that 'a' is located anywhere but the stack. But it's very different from a 'scope' parameter, which expressly forbids this, as opposed to the fortuitous coincidence that allows you to know that 'x = &a' is an error in this particular case. To have 'scope ref' implicitly mean ' temp ref' would be conflating two different features, I think, which only happen to have one thing in common.
Apr 03 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
After some thinking on topic I come to conclusion that rvalue 
refs _should_ be "scope ref" and stuff like "ref int f( temp ref 
int x) { return x; }" is invalid. I can see no valid use case for 
such an error-prone case. Contrary, "scope ref" feels just like 
it was designed for this task, also a good moment to actually 
define what "scope" means.
Apr 04 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Thursday, 4 April 2013 at 07:52:51 UTC, Dicebot wrote:
 After some thinking on topic I come to conclusion that rvalue 
 refs _should_ be "scope ref" and stuff like "ref int f( temp 
 ref int x) { return x; }" is invalid. I can see no valid use 
 case for such an error-prone case. Contrary, "scope ref" feels 
 just like it was designed for this task, also a good moment to 
 actually define what "scope" means.
I am beginning to like scope ref also. It just fits. Nice that we agree on that now - but I still miss Kenji's, Walters and Andrei's blessing. Otherwise I think it would be ripe for a pull request. Or there is any difficulty?
Apr 04 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Thursday, 4 April 2013 at 14:43:26 UTC, Namespace wrote:
 On Thursday, 4 April 2013 at 07:52:51 UTC, Dicebot wrote:
 After some thinking on topic I come to conclusion that rvalue 
 refs _should_ be "scope ref" and stuff like "ref int f( temp 
 ref int x) { return x; }" is invalid. I can see no valid use 
 case for such an error-prone case. Contrary, "scope ref" feels 
 just like it was designed for this task, also a good moment to 
 actually define what "scope" means.
I am beginning to like scope ref also. It just fits. Nice that we agree on that now - but I still miss Kenji's, Walters and Andrei's blessing. Otherwise I think it would be ripe for a pull request. Or there is any difficulty?
I don't know. My opinion has no value here. I may advice to write a DIP that makes more accent on theoretical side of problem - what "scope" currently is, how it combines with ref now, how it should combine, how Andrei's DIP fits in the picture, how it fits overall type system, what are possible code breakage scenarios, what are typical use cases for this feature etc. If such DIP and matching pull request do exist, it is only matter of agreement (with Andrei/Walter) about points stated in DIP.
Apr 04 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
 I don't know. My opinion has no value here.
I know. But I wanted to hear just your personal opinion about the code and if you have any suggestions or anything.
 I may advice to write a DIP that makes more accent on 
 theoretical side of problem - what "scope" currently is, how it 
 combines with ref now, how it should combine, how Andrei's DIP 
 fits in the picture, how it fits overall type system, what are 
 possible code breakage scenarios, what are typical use cases 
 for this feature etc. If such DIP and matching pull request do 
 exist, it is only matter of agreement (with Andrei/Walter) 
 about points stated in DIP.
Hmm, I don't know if I could write a long and good text for the DIP. My english is very limited and not free of failures. I still had hoped that Kenji or some other find the time, to see over my code and to make a DIP/Pull Request.
Apr 04 2013
next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
2013/4/5 Namespace <rswhite4 googlemail.com>

 Hmm, I don't know if I could write a long and good text for the DIP. My
 english is very limited and not free of failures.
 I still had hoped that Kenji or some other find the time, to see over my
 code and to make a DIP/Pull Request.
Timely guess. I roughly implemented it in my experimental branch. https://github.com/9rnsr/dmd/commits/new_inref I need more cleanup for it, but it would work as we expected. Kenji Hara
Apr 04 2013
parent "Namespace" <rswhite4 googlemail.com> writes:
On Thursday, 4 April 2013 at 16:31:06 UTC, kenji hara wrote:
 2013/4/5 Namespace <rswhite4 googlemail.com>

 Hmm, I don't know if I could write a long and good text for 
 the DIP. My
 english is very limited and not free of failures.
 I still had hoped that Kenji or some other find the time, to 
 see over my
 code and to make a DIP/Pull Request.
Timely guess. I roughly implemented it in my experimental branch. https://github.com/9rnsr/dmd/commits/new_inref I need more cleanup for it, but it would work as we expected. Kenji Hara
That works well. Thanks for your efforts.
Apr 04 2013
prev sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Thursday, 4 April 2013 at 16:21:50 UTC, Namespace wrote:
 I don't know. My opinion has no value here.
I know. But I wanted to hear just your personal opinion about the code and if you have any suggestions or anything.
 I may advice to write a DIP that makes more accent on 
 theoretical side of problem - what "scope" currently is, how 
 it combines with ref now, how it should combine, how Andrei's 
 DIP fits in the picture, how it fits overall type system, what 
 are possible code breakage scenarios, what are typical use 
 cases for this feature etc. If such DIP and matching pull 
 request do exist, it is only matter of agreement (with 
 Andrei/Walter) about points stated in DIP.
Hmm, I don't know if I could write a long and good text for the DIP. My english is very limited and not free of failures. I still had hoped that Kenji or some other find the time, to see over my code and to make a DIP/Pull Request.
Well, I doubt there are that many native speakers here which will be shocked by bad English :) But if you gather all data mentioned (see also Kenji's comment), I can write DIP itself for you. Type system changes should be studied in smallest details as those have have very long term consequences and incredibly hard to replace with better solutions later.
Apr 04 2013
next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 Well, I doubt there are that many native speakers here which 
 will be shocked by bad English :) But if you gather all data 
 mentioned (see also Kenji's comment), I can write DIP itself 
 for you. Type system changes should be studied in smallest 
 details as those have have very long term consequences and 
 incredibly hard to replace with better solutions later.
That sounds good. Then I will try over the weekend to collect all the necessary data and post them here. Then you can take a quick look, whether you have enough information or if I need a little late filing.
Apr 04 2013
prev sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
I am currently in the process to collect the necessary 
information and would gladly give you the previous data. Then you 
could already take a look on it, if you still need something or 
if something is missing and if, what. Then I have a clearer idea. 
That would certainly be very nice of you.
For this purpose it would be good to have your email. Or should I 
post the DIP proposal here?
Apr 06 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Saturday, 6 April 2013 at 17:50:31 UTC, Namespace wrote:
 I am currently in the process to collect the necessary 
 information and would gladly give you the previous data. Then 
 you could already take a look on it, if you still need 
 something or if something is missing and if, what. Then I have 
 a clearer idea. That would certainly be very nice of you.
 For this purpose it would be good to have your email. Or should 
 I post the DIP proposal here?
m.strashun at gmail
Apr 06 2013
prev sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
I also think writing DIP would be better.

I can tell some reasonable points about 'scope ref'.
- 'in ref' has been allowed from 2.060 (
http://d.puremagic.com/issues/show_bug.cgi?id=8105)
- 'scope ref' is still disallowed. ("Error: scope cannot be ref or out")
- 'scope' means "the reference cannot escape from local scope".
  And an rvalue reference cannot escape from passed function. There is
consistent semantics.
- 'in' is equivalent to 'const scope' ( http://dlang.org/function.html
)<http://dlang.org/function.html>
  So, 'in ref' is equivalent to 'const scope ref'.
- Currently 'scope' affects to delegate parameter. In other cases, 'scope'
has no meaning.

I recognize that Jonathan had opposed to 'in ref' because it had supported
just only "const rvalue reference" (like 'cosnt T&' in C++). In D, 'const'
means physical const, so he has thought that mutable rvalue reference
should be supported in D.

So, I think 'scope ref' is good proposal against the Jonathan's objection.


Kenji Hara

<http://dlang.org/function.html>2013/4/5 Dicebot <m.strashun gmail.com>

 On Thursday, 4 April 2013 at 14:43:26 UTC, Namespace wrote:

 On Thursday, 4 April 2013 at 07:52:51 UTC, Dicebot wrote:

 After some thinking on topic I come to conclusion that rvalue refs
 _should_ be "scope ref" and stuff like "ref int f( temp ref int x) { return
 x; }" is invalid. I can see no valid use case for such an error-prone case.
 Contrary, "scope ref" feels just like it was designed for this task, also a
 good moment to actually define what "scope" means.
I am beginning to like scope ref also. It just fits. Nice that we agree on that now - but I still miss Kenji's, Walters and Andrei's blessing. Otherwise I think it would be ripe for a pull request. Or there is any difficulty?
I don't know. My opinion has no value here. I may advice to write a DIP that makes more accent on theoretical side of problem - what "scope" currently is, how it combines with ref now, how it should combine, how Andrei's DIP fits in the picture, how it fits overall type system, what are possible code breakage scenarios, what are typical use cases for this feature etc. If such DIP and matching pull request do exist, it is only matter of agreement (with Andrei/Walter) about points stated in DIP.
Apr 04 2013
next sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote:
 I can tell some reasonable points about 'scope ref'.
 - 'in ref' has been allowed from 2.060 (
 http://d.puremagic.com/issues/show_bug.cgi?id=8105)
 - 'scope ref' is still disallowed. ("Error: scope cannot be ref 
 or out")
 - 'scope' means "the reference cannot escape from local scope".
   And an rvalue reference cannot escape from passed function. 
 There is
 consistent semantics.
 - 'in' is equivalent to 'const scope' ( 
 http://dlang.org/function.html
 )<http://dlang.org/function.html>
   So, 'in ref' is equivalent to 'const scope ref'.
 - Currently 'scope' affects to delegate parameter. In other 
 cases, 'scope'
 has no meaning.

 I recognize that Jonathan had opposed to 'in ref' because it 
 had supported
 just only "const rvalue reference" (like 'cosnt T&' in C++). In 
 D, 'const'
 means physical const, so he has thought that mutable rvalue 
 reference
 should be supported in D.

 So, I think 'scope ref' is good proposal against the Jonathan's 
 objection.

 Kenji Hara
My argument would be that 'scope ref' and ' temp ref' are two different horns of the same devil, really. The problem with ' temp ref' is that it's "syntax creep", adding a new storage class for limited reward. But 'scope ref' is equally problematic, because if it *does* allow returning the parameter by reference it will be deceptively different from simply what 'scope' would do. So the syntax creep would be replaced by the confusing nature of 'ref', 'scope', and 'scope ref': ref int func(ref int a) { return a; } // Okay ref int func2(scope int a) { return *new int; //return a; // No good, error: a is 'scope' } // Okay: 'scope ref' means something different from 'scope' ref int func3(scope ref int a) { return a; } ref int testFuncs(ref int y) { int x; return func(x); // Error: ref return assumed local as x return func(y); // Okay: y is from outside and returnable return func2(x); // Okay: 'scope' ensures x not returned return func2(y); // Okay return func3(x); // Error: ref return assumed local as x return func3(y); // Okay: y outside return func3(53); // Error: temp 53 is local } If 'scope' were defined as above, 'scope ref' could not be used to say that you *also* want the parameter to be 'scope' in addition to 'scope ref'. This leads into the remaining issue with DIP25, which is that 'scope' would be useful to tell the calling function that the passed-in variable will not be 'ref' returned, as in func2() above. DIP25 may want 'scope' to help add flexibility to what may or may not be returned. Dicebot's suggestion, that ref int func3(scope ref int a) {} above be banned from returning 'a', would solve this problem. In this case 'scope ref' would mean both 'scope' *and* ' temp ref'. It does however conflate the two features, making it impossible to return an rvalue ref parameter by ref. It may be that the cases where you actually *want* to return an rvalue ref parameter by reference are so rare that no one will miss that you can't do it. Or, conversely, it may be so rare that you want to specify 'scope' on your parameter in addition to 'scope ref' that no one will miss not being able to do that either. But one of these solutions must be accepted is 'scope ref' is to mean what is suggested. The other horn of the devil is to swallow the distasteful pill and allow ' temp ref', 'ref&', or some other "syntax creep".
Apr 04 2013
prev sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote:
 I also think writing DIP would be better.
 ...
Btw, Kenji, what do you think about redefining "in" to "const scope ref" and allowing compiler to chose how variable exactly is passed ("auto ref" with no template bloat)? Within those restrictions plain values should be indistinguishable from const rvalue refs. Will make "in" also much more meaningful as a separate entity.
Apr 05 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 5 April 2013 at 07:48:38 UTC, Dicebot wrote:
 On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote:
 I also think writing DIP would be better.
 ...
Btw, Kenji, what do you think about redefining "in" to "const scope ref" and allowing compiler to chose how variable exactly is passed ("auto ref" with no template bloat)? Within those restrictions plain values should be indistinguishable from const rvalue refs. Will make "in" also much more meaningful as a separate entity.
To change "in" from "const scope" to "const scope ref" is IMO a bad idea. It will break code and it's not intuitive. In my opinion we should use "ref" in combination with something else (in this case "scope"). But that is my personal opinion.
Apr 05 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Friday, 5 April 2013 at 08:35:03 UTC, Namespace wrote:
 On Friday, 5 April 2013 at 07:48:38 UTC, Dicebot wrote:
 On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote:
 I also think writing DIP would be better.
 ...
Btw, Kenji, what do you think about redefining "in" to "const scope ref" and allowing compiler to chose how variable exactly is passed ("auto ref" with no template bloat)? Within those restrictions plain values should be indistinguishable from const rvalue refs. Will make "in" also much more meaningful as a separate entity.
To change "in" from "const scope" to "const scope ref" is IMO a bad idea. It will break code and it's not intuitive. In my opinion we should use "ref" in combination with something else (in this case "scope"). But that is my personal opinion.
How so? It does not break anything, as all "const scope" cases can be processed with "const scope ref", in fact, compiler should be allowed to degrade first to latter. Regarding meaning - if "scope ref" means permissive rvalues (mutable ones), then "const scope ref" means closer match for C++ "const &" - constant references that can't escape scope. I actually have an impression you do really want exactly "const scope ref" considering frequent references to C++. Tricky part as far as I can see is ABI - one needs to be able to accept both value and ref parameters within same function signature. Possible but may be too hacky to implement.
Apr 05 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 How so? It does not break anything, as all "const scope" cases 
 can be processed with "const scope ref", in fact, compiler 
 should be allowed to degrade first to latter. Regarding meaning 
 - if "scope ref" means permissive rvalues (mutable ones), then 
 "const scope ref" means closer match for C++ "const &" - 
 constant references that can't escape scope.
What I meant was simply, that users which are using already "in ref" would get then the error: "redundant storage class: ref" because 'in' would contains 'ref' already. That's the whole reason of my rejection. ;)
 I actually have an impression you do really want exactly "const 
 scope ref" considering frequent references to C++.
No, I like to get 'scope ref' just as much as 'in ref' / 'scope const ref'. Mutable rvalue references are absolutely useful. How did you get the idea?
Apr 05 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Friday, 5 April 2013 at 08:57:35 UTC, Namespace wrote:
 How so? It does not break anything, as all "const scope" cases 
 can be processed with "const scope ref", in fact, compiler 
 should be allowed to degrade first to latter. Regarding 
 meaning - if "scope ref" means permissive rvalues (mutable 
 ones), then "const scope ref" means closer match for C++ 
 "const &" - constant references that can't escape scope.
What I meant was simply, that users which are using already "in ref" would get then the error: "redundant storage class: ref" because 'in' would contains 'ref' already. That's the whole reason of my rejection. ;)
I am surprised to hear that redundant storage classes are considered an error by dmd :) Makes no sense for me, typical "generic code gen" use case story.
 I actually have an impression you do really want exactly 
 "const scope ref" considering frequent references to C++.
No, I like to get 'scope ref' just as much as 'in ref' / 'scope const ref'. Mutable rvalue references are absolutely useful. How did you get the idea?
Sorry then, I have misunderstood you then. I do want both "scope ref" and "const scope ref" too, but I was thinking that simple easy-to-use shortcut (in) should match most idiomatic and safe use case, and that should be "scope const ref". With an additional benefit of being able to replace values with refs transparently due to storage class/qualifier restrictions. I don't have strong opinion here, it is just an idea that came to my mind today and felt tempting ;)
Apr 05 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 I am surprised to hear that redundant storage classes are 
 considered an error by dmd :) Makes no sense for me, typical 
 "generic code gen" use case story.
http://dpaste.1azy.net/3ef7a084
 Sorry then, I have misunderstood you then. I do want both 
 "scope ref" and "const scope ref" too, but I was thinking that 
 simple easy-to-use shortcut (in) should match most idiomatic 
 and safe use case, and that should be "scope const ref". With 
 an additional benefit of being able to replace values with refs 
 transparently due to storage class/qualifier restrictions.

 I don't have strong opinion here, it is just an idea that came 
 to my mind today and felt tempting ;)
I like it also but was afraid that it could break user code. 'in ref' is allowed since 2.060 and many users use 'in' because it is shorter than 'const' and feels like the opposite of 'out'. :/ Otherwise that would be a good idea. Let's hear what Kenji says.
Apr 05 2013
parent kenji hara <k.hara.pg gmail.com> writes:
I also think that we should not change current `in` meaning.
It is already used as the shorthand of `const` widely, and it has value
semantics (make a copy of given argument). That's the major motivation to
add new syntax "scope ref" and "in ref".

Kenji Hara


2013/4/5 Namespace <rswhite4 googlemail.com>

 I am surprised to hear that redundant storage classes are considered an
 error by dmd :) Makes no sense for me, typical "generic code gen" use case
 story.
http://dpaste.1azy.net/**3ef7a084 <http://dpaste.1azy.net/3ef7a084> Sorry then, I have misunderstood you then. I do want both "scope ref" and
 "const scope ref" too, but I was thinking that simple easy-to-use shortcut
 (in) should match most idiomatic and safe use case, and that should be
 "scope const ref". With an additional benefit of being able to replace
 values with refs transparently due to storage class/qualifier restrictions.

 I don't have strong opinion here, it is just an idea that came to my mind
 today and felt tempting ;)
I like it also but was afraid that it could break user code. 'in ref' is allowed since 2.060 and many users use 'in' because it is shorter than 'const' and feels like the opposite of 'out'. :/ Otherwise that would be a good idea. Let's hear what Kenji says.
Apr 05 2013
prev sibling parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Thursday, 4 April 2013 at 07:52:51 UTC, Dicebot wrote:
 After some thinking on topic I come to conclusion that rvalue 
 refs _should_ be "scope ref" and stuff like "ref int f( temp 
 ref int x) { return x; }" is invalid. I can see no valid use 
 case for such an error-prone case.
Perhaps they should, but at least I will give the use case I was thinking of. If you've got a large struct, you don't want to pass it by value. Say you've got two functions which process and return a Large, and they accept rvalue refs. It might not be too much to ask that a Large always be an lvalue, but let's say you want to pass it directly by value for some reason. struct Large { ... } ref Large process1( temp ref Large a) { return a; } ref Large process2( temp ref Large a) { return a; } Large* lar = &process2(process1(Large("Pass"," a ", "Large", "here"))); The use case would allow this to work. And with the kind of error checking suggested in DIP25, this kind of construction would not actually be error prone. 'lar' would be understood as locally derived and could not escape the function it was defined in. But to speak to your point, this kind of single expression chaining of ref functions might be so rare that there's no great reason to allow it in tandem with rvalues.
Apr 04 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Friday, 5 April 2013 at 00:12:33 UTC, Zach the Mystic wrote:
 struct Large { ... }
 ref Large process1( temp ref Large a) { return a; }
 ref Large process2( temp ref Large a) { return a; }

 Large* lar = &process2(process1(Large("Pass"," a ", "Large", 
 "here")));
This is exactly type of code I consider to be bad style and want to see banned. Function that gets rvalue ref should never return it as it knows nothing about its lifetime. Actually, I can't even find scope definition for temporaries in dlang.org, but it is hardly a good thing to rely on anyway. Best is to assume that when function is gone, so is rvalue temporary. Your code begs for using plain refs and storing Large in a stack variable before calling function chain. May look a bit less convenient but much more reliable and understandable.
Apr 05 2013
parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Friday, 5 April 2013 at 07:45:33 UTC, Dicebot wrote:
 On Friday, 5 April 2013 at 00:12:33 UTC, Zach the Mystic wrote:
 struct Large { ... }
 ref Large process1( temp ref Large a) { return a; }
 ref Large process2( temp ref Large a) { return a; }

 Large* lar = &process2(process1(Large("Pass"," a ", "Large", 
 "here")));
This is exactly type of code I consider to be bad style and want to see banned. Function that gets rvalue ref should never return it as it knows nothing about its lifetime. Actually, I can't even find scope definition for temporaries in dlang.org, but it is hardly a good thing to rely on anyway. Best is to assume that when function is gone, so is rvalue temporary.
It may be bad style. (I don't know if it's bad style.) But there is significant thought (such as in DIP25) going into the idea that the programmer doesn't even *need* to track the lifetime of a reference, that the compiler can do it automatically. I don't think it's documented, but there is already an error issued for local variables which are returned by reference, which is the same behavior as 'scope' described. ref int func() { int y; return y; // Error: may not be escaped } There is no current checking, however, for returning the result of a function which returns ref. ref int func(ref int a) { return a; } ref int func2() { int x; return func(x); // Passes when it should error, x escaped } DIP25, to be on the safe side, proposes that since func() takes a ref, it must be assumed to return the ref it takes. So func(x) will be treated as a local since x is a local. The only flaw with DIP25 is that it's actually *too* safe, and it will shut down some cases which are perfectly fine: ref int copy(ref int a) { int *b = new int; *b = a; return *b; // return by ref } I have tried to address this issue elsewhere (and I actually need to make formal proposals which I haven't done yet), but the main point is that even accepting a temporary rvalue is the kind of thing which can be tracked at the call site, and not the function itself. ref int func(ref int a) { return a; } ref int func2() { int x; return func(x); // Error, according to DIP25 return func(25); // Error also, temp 25 is local, just like x static int* y; return func(y); // Okay because y is not local } So there are two different issues going on. Now what's the big deal, you may ask. Any function designed to accept an rvalue temporary can't possibly want to return that parameter by reference. And you may be right. In fact, the only reason I know to allow it was mentioned above, because it would allow efficient chaining of operations on a single entity passed by reference instead of by value, with each function modifying it before passing it on. But it's the *caller* who needs to know how local the reference is, not the receiving function. And that leads me into the other issue, which is that I had thought 'scope' would be a great way to tell a calling function "no, this ref will not be returned to you". (This is the issue I need to make a formal proposal on.) And that leads to a direct contradiction with the proposed use of 'scope ref', as I have written in my answer to Kenji Hara's defense of 'scope ref'. ref int func(scope int a) { return *new int; // Okay return a; //Error: can't return a parameter marked scope } Now the checking used by DIP25 could call func() safely: ref int testFunc() { int x; return func(x); // Okay, I know x will not be returned } So 'scope' and 'scope ref' would mean two different things, and there might be some cases where you only want one of the features and not both. To address this issue, I thought of a slightly desperate way to actually resolve this problem without any new storage class, such as 'ref&' or ' temp ref'. In order to indicate 'scope' in addition to 'scope ref', you'd simply write 'scope scope ref'. Two scopes! The defense of this position is that the actual use of 'scope' by itself would rarely be used, and so the strange appearance of two scopes would almost never happen.
 Your code begs for using plain refs and storing Large in a 
 stack variable before calling function chain. May look a bit 
 less convenient but much more reliable and understandable.
Yes, this issue would be simplified by simply saying that any function which accepts rvalue temporaries must treat those parameters as locals and not allow returning them. It imposes a minor inconvenience on the programmer who must declare an lvalue to use any function which *does* return a reference to the parameter. I actually think this is a sound design choice, but at least it will be a choice and not a "lucky" accident. One last thing about 'scope ref', which would be usable for the new feature, assuming the design choice just mentioned was accepted. It's not as obvious that it implicitly allows rvalue temporaries as something blunt like ' temp ref' would be, or as inconspicuous as 'ref&' would be. Also, it sort of suggests that ordinary 'scope' is not in fact passed by ref, which I is somewhat misleading. So it does save on syntax creep, but it also has those three disadvantages. I think that's all I have to say about this topic!
Apr 06 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Saturday, 6 April 2013 at 07:50:10 UTC, Zach the Mystic wrote:
 ...
Ye, I know it and I hate DIP25. It tries to limit references to allow them in safe and I hate safe as much. Type system will lack plain "non-null pointer" type then. Sad I can do nothing about it.
Apr 06 2013
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 'scope ref': The only existing documentation on scope 
 parameters: http://dlang.org/function.html suggests that 
 references to them simply cannot leave the function they find 
 themselves in. But this is *not* what the temp ref feature is 
 about. Say you have this temp ref function:

 ref int func( temp ref int a) { return a; }

 According to the spec, it clearly violates 'scope', but is 
 nonetheless valid and safe, as far as I can tell. The compiler 
 can easily track the scope of a given lvalue at the call site:

 static int* x;
 static int y;
 x = *func(3); // Error: result of func(3) is assumed to be local
 x = *func(y); // Pass: address of y is known to be global

 This kind of safety checking is not yet implemented, but is 
 suggested in DIP25, http://wiki.dlang.org/DIP25 . I believe it 
 is the right way to go. The locality of the return by reference 
 is assumed to be as local as the reference which is passed into 
 it. So the temp '3' reference would make the result of func(3) 
 yield a local, barring any other information which would allow 
 the compiler to safely assume otherwise. In essence, ' temp 
 ref' can escape its scope safely because the locality of the 
 result is not its responsibility.
As far as I know Andrei works on DIP25 and as far as I know from his thread in D.bugs he has already began with the implementation. But I agree with you that 'scope ref' should be smart enough to
 ' ref': I like this less than 'ref&' because it is even less 
 clear what it means than 'ref&' is. The two problems with 
 'ref&', so far as I understand it, are 1, that it looks like a 
 one-character hack which generally not well-liked in this 
 community, and 2, it could be confused with a double-reference. 
 I personally don't think I'm going to confuse 'ref&' with 'ref 
 *'. At least 'ref&' gives a hint that it has something to do 
 with taking the address of something. ' ref' is nothing more 
 than saying, "Hey, I can take ' ' and put it before keyword 
 'ref'. Look at me!". I'm not for it at all.
:D Yes, there already is some truth to it.
 If 'ref&' or ' ref' are rejected on the basis of their being 
 one-character hacks, then the search is on for a good ' ' word 
 or an existing keyword which does the trick. I wish 'scope' 
 could cover it, but I personally don't see how that keyword as 
 defined covers this feature as proposed.
I think with Andreis improvements on the current ref implementation, scope ref could do the job. It must only be smart enough to detect such cases as you described above.
 I looked for other existing keywords to do the job, but I 
 didn't find one which met my personal sense of what would work. 
 'auto ref' would have been a perfect name for it if 'auto ref' 
 hadn't already found great use in templates. All I have, 
 therefore, are ' val' and, given this post, ' temp':

 void func( val ref int a) {}
 void func( temp ref int a) {}

 I think ' val' is pretty good. I don't think this feature 
 merits its own keyword, so the ' ' is there to stay, but at 
 least ' val' is only four letters long, exactly the same number 
 of characters as 'auto'.

 Does anyone else have a better ' ttribute' for this feature, 
 assuming one-char hacks are out of the question?
I don't like val because I don't see the coherence between rvalue references and value references. Or I don't understand it right now. But temp would be a good alternative if some others with more knowledge than me think also, that scope ref isn't the right way to go and ref/ref& are dirty hacks.
Apr 04 2013
prev sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Wednesday, 3 April 2013 at 06:19:58 UTC, Namespace wrote:
 For all of these a proposal and a finished implementation of 
 mine is ready, you have to choose and to review only. :)
Hot stuff!
Apr 03 2013
prev sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
I think 'scope ref' is better.
'in' = 'const scope', then 'in ref' = 'const scope ref'.

bool opEquals(in ref T rhs) const { ... }

Kenji Hara
2013/03/30 21:06 "Namespace" <rswhite4 googlemail.com>:

 As far as I studied the code, something like  ref isn't possible, because
 ref is already a keyword. Except as Pseudo-property. But this is a
 combination of ' ' and 'ref' so that both, ' ref' and '  ref' would be
 valid.
 I still like the idea of '&A'.
Apr 02 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Tuesday, 2 April 2013 at 17:30:33 UTC, kenji hara wrote:
 I think 'scope ref' is better.
 'in' = 'const scope', then 'in ref' = 'const scope ref'.

 bool opEquals(in ref T rhs) const { ... }

 Kenji Hara
 2013/03/30 21:06 "Namespace" <rswhite4 googlemail.com>:

 As far as I studied the code, something like  ref isn't 
 possible, because
 ref is already a keyword. Except as Pseudo-property. But this 
 is a
 combination of ' ' and 'ref' so that both, ' ref' and '  ref' 
 would be
 valid.
 I still like the idea of '&A'.
As far as I know Jonathan was strict against it, or not? But that sounds and looks nice and would be very easy to implement.
Apr 02 2013
parent "Namespace" <rswhite4 googlemail.com> writes:
My try for scope ref/in ref:
https://github.com/Dgame/dmd/tree/in_ref
Apr 02 2013
prev sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 30.03.2013 12:04, schrieb Namespace:
 I have to agree on that. My first impression was that ref& is equal to
 c++11 &&

 Kind Regards
 Benjamin Thaut
Ok, it seems that I think differently. And what is the general opinion of '&A' instead of 'ref &A'? It has all the benefits that I described in my first post, but it may not be so confusing. If you like to ask "why not A&": That is more complex as it seems to be, a opinion which is shared by Jonathan. And I sincerely hope that no one is annoyed about my attempts to solve this problem.
No I highly appreciate it, that you are trying to solve the problem. The current state of the language on this is annoying and it needs to be fixed. I personally would like &A the question is if this is the "D-Way". Maybe we should add a new keyword like "vref" for "value reference". Kind Regards Benjamin Thaut
Mar 30 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
 No I highly appreciate it, that you are trying to solve the 
 problem. The current state of the language on this is annoying 
 and it needs to be fixed.

 I personally would like &A the question is if this is the 
 "D-Way". Maybe we should add a new keyword like "vref" for 
 "value reference".

 Kind Regards
 Benjamin Thaut
That's nice to hear. I was afraid I would be too intrusive on this. And I've finally did it: A& works now. It was a bit tricky, but now it works nicely. Here a quick example: void bar1(A& a) { } // OK void bar2(A&* a) { } // Error: '&' can not be used in combination with '*' void bar3(A*& a) { } // Error: '&' can not be used in combination with '*' void bar4(const A& a) { } // OK void bar5(ref A& a) { } // Error: conflicting storage class '&' and ref and for templates: void bar(T)(T& t) { writeln(t); } Thoughts?
Mar 30 2013
parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Saturday, 30 March 2013 at 14:37:11 UTC, Namespace wrote:
 That's nice to hear. I was afraid I would be too intrusive on 
 this.
 And I've finally did it: A& works now. It was a bit tricky, but 
 now it works nicely. Here a quick example:

 void bar1(A& a) { } // OK
 void bar2(A&* a) { } // Error: '&' can not be used in 
 combination with '*'
 void bar3(A*& a) { } // Error: '&' can not be used in 
 combination with '*'
 void bar4(const A& a) { } // OK
 void bar5(ref A& a) { } // Error: conflicting storage class '&' 
 and ref

 and for templates:

 void bar(T)(T& t) {
 	writeln(t);
 }

 Thoughts?
It's esoteric, which is bad, but concise, which is good. I think perhaps the annoying aspect of this feature is how attractive it would be to just get the power of the feature implicitly without needing a new attribute or keyword. To get it implicitly, and only have an attribute for when you *don't want an rvalue, e.g.: void foo( lvalue ref T a) {} ...would break code, but is nonetheless less something to consider also.
Mar 31 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 It's esoteric, which is bad, but concise, which is good. I 
 think perhaps the annoying aspect of this feature is how 
 attractive it would be to just get the power of the feature 
 implicitly without needing a new attribute or keyword.
Maybe you're right. But I like the idea that, if you want strict lvalues, you use 'ref' and if you don't care, you use the C++ style. I think that would be the best idea. But currently I have a problem with the implemenation of 'A&'. I do not know how to convey the fact that behind the type is a '&'. IMO the correct D way is to create a new type like TypePointer -> TypeRvRef. But my attempts failed so far to create such type. Because of that I decided to declare a boolean flag 'isRvRef' inside of the basic Type struct which I set to TRUE if a '&' is behind the type. This works and don't break any code but I think that should be fixed by someone with more knowledge. But I think also that this rvalue problem has a very low priority. So if we want to resolve this issue, then we need to do it yourself. If someone wants to help me, the code and the current solution is on github: https://github.com/Dgame/dmd/tree/rvalueRef
 To get it implicitly, and only have an attribute for when you 
 *don't want an rvalue, e.g.:

 void foo( lvalue ref T a) {}

 ...would break code, but is nonetheless less something to 
 consider also.
Walter hate to break code, so the introduction of that would be even much less likely. And yes you're right, when I said 'property' I meant an attribute. ;)
Apr 01 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 But currently I have a problem with the implemenation of 'A&'. 
 I do not know how to convey the fact that behind the type is a 
 '&'. IMO the correct D way is to create a new type like 
 TypePointer -> TypeRvRef. But my attempts failed so far to 
 create such type.
 Because of that I decided to declare a boolean flag 'isRvRef' 
 inside of the basic Type struct which I set to TRUE if a '&' is 
 behind the type. This works and don't break any code but I 
 think that should be fixed by someone with more knowledge.
 But I think also that this rvalue problem has a very low 
 priority.
 So if we want to resolve this issue, then we need to do it 
 yourself.
 If someone wants to help me, the code and the current solution 
 is on github:
 https://github.com/Dgame/dmd/tree/rvalueRef
I could finally fix the problem. Now for rvalue references an extra type is created: TypeRvRef. But this solution does not work with templates. I do not yet know how to solve this, but maybe someone knows advice. Code: https://github.com/Dgame/dmd/tree/rvalueRef2
Apr 01 2013
parent "Namespace" <rswhite4 googlemail.com> writes:
 I could finally fix the problem.
 Now for rvalue references an extra type is created: TypeRvRef.
 But this solution does not work with templates. I do not yet 
 know how to solve this, but maybe someone knows advice.
 Code: https://github.com/Dgame/dmd/tree/rvalueRef2
Since I still have no idea how to solve the template problem (I tried it the last 6 hours - without success) I have one final alternative: final ref. This would be as easy to implement as my first solution, but of course does not look that nice and is much longer than the C++ style. Any ideas? Opinions? Suggestions or ideas to solve the template problem are also welcome. :)
Apr 02 2013
prev sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Saturday, 30 March 2013 at 13:07:44 UTC, Benjamin Thaut wrote:
 Am 30.03.2013 12:04, schrieb Namespace:
 I have to agree on that. My first impression was that ref& is 
 equal to
 c++11 &&

 Kind Regards
 Benjamin Thaut
Ok, it seems that I think differently. And what is the general opinion of '&A' instead of 'ref &A'? It has all the benefits that I described in my first post, but it may not be so confusing. If you like to ask "why not A&": That is more complex as it seems to be, a opinion which is shared by Jonathan. And I sincerely hope that no one is annoyed about my attempts to solve this problem.
No I highly appreciate it, that you are trying to solve the problem. The current state of the language on this is annoying and it needs to be fixed. I personally would like &A the question is if this is the "D-Way". Maybe we should add a new keyword like "vref" for "value reference". Kind Regards Benjamin Thaut
Although adding new keywords is not smiled upon at this point, it might actually be worth it in this case.
Mar 30 2013
prev sibling parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Saturday, 30 March 2013 at 09:17:17 UTC, Namespace wrote:
 The major downside is that if you don't come from C++ it's 
 hard to understand why 'ref &' means what you propose. The 
 major upsides are, as you mention, it's very concise and 
 perfectly intuitive if you DO come from C++. In the spirit of 
 trying to come up with something for comparison, the best 
 attribute I've thought of so far is ' val':

 void bar1( val ref A a) { }

 The advantage is that it's consistent with my understanding of 
 the general approach to adding things to D at this point. But 
 that's also it's disadvantage: it's nothing more than a 
 mundane attribute.
Yes you're right. But I just think that a property does not make sense here, because we mix then two different things: storage classes and properties. This strikes me as wrong. When I implemented the pseudo-property ref, I realized this. It seemed inconsistent compared to the rest of the D syntax. And since D, syntactically as well as linguistically (D provides direct access to C / C++), is a descendant of C++, I'd prefer to take a kind of hybrid: ref&.
Just a technical point, I believe your use of the term "property" should be replaced with the term "attribute". means attribute, of which there are two kinds, built-in and user defined. Built-in attributes themselves are little more than keywords which haven't acquired "tenure", so to speak - the confidence of the language designers that they merit the full status of a no- keyword.
Mar 31 2013
parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Monday, 1 April 2013 at 00:37:07 UTC, Zach the Mystic wrote:
 Just a technical point, I believe your use of the term 
 "property" should be replaced with the term "attribute".   
 means attribute, of which there are two kinds, built-in and 
 user defined. Built-in attributes themselves are little more 
 than keywords which haven't acquired "tenure", so to speak - 
 the confidence of the language designers that they merit the 
 full status of a no-  keyword.
To be even more precise, some built-in attributes, such as 'ref', 'in', and 'out' function parameters, don't even require the and are indeed full-fledged keywords too.
Mar 31 2013