digitalmars.D - My thoughts & tries with rvalue references
- Namespace (39/39) Mar 29 2013 Hey guys,
- Zach the Mystic (12/51) Mar 29 2013 The major downside is that if you don't come from C++ it's hard
- Namespace (15/26) Mar 30 2013 Yes you're right. But I just think that a property does not make
- Minas Mina (5/12) Mar 30 2013 Because & in C++ means "by ref".
- Namespace (15/19) Mar 30 2013 You are undermining my authority. :P
- Minas Mina (2/2) Mar 30 2013 Personally yes, I prefer @ref more. But you are right that it's
- Benjamin Thaut (5/15) Mar 30 2013 I have to agree on that. My first impression was that ref& is equal to
- Namespace (8/12) Mar 30 2013 Ok, it seems that I think differently.
- Namespace (5/5) Mar 30 2013 As far as I studied the code, something like @ref isn't possible,
- Namespace (60/65) Apr 02 2013 I have to disagree with me here.
- Zach the Mystic (39/56) Apr 02 2013 '@ref' is actually my least favorite choice. Of all presented, my
- Zach the Mystic (2/35) Apr 02 2013 s/ref int b/ref int a/
- Namespace (13/21) Apr 02 2013 I like 'ref&' also, but the reaction seemed to imply that it
- Namespace (6/6) Apr 03 2013 It would interest me which of the suggestions would be rather
- Dicebot (5/11) Apr 03 2013 I am against introducing new one-symbol meanings, it always looks
- Namespace (3/15) Apr 03 2013 So you were against the introduction of ravalue references or do
- Dicebot (4/6) Apr 04 2013 I am against whole "ref" design in D and consider it a mistake :)
- Namespace (3/7) Apr 03 2013 Addendum to scope ref: It could mean: "This ref parameter accepts
- Zach the Mystic (64/70) Apr 03 2013 I simply can't reconcile the stated intention of 'scope'
- Zach the Mystic (2/6) Apr 03 2013 s/*func/&func/
- Zach the Mystic (16/38) Apr 03 2013 On the other hand, a '@temp ref' parameter *should* be prevented
- Dicebot (6/6) Apr 04 2013 After some thinking on topic I come to conclusion that rvalue
- Namespace (5/11) Apr 04 2013 I am beginning to like scope ref also. It just fits.
- Dicebot (9/20) Apr 04 2013 I don't know. My opinion has no value here. I may advice to write
- Namespace (6/15) Apr 04 2013 Hmm, I don't know if I could write a long and good text for the
- kenji hara (5/9) Apr 04 2013 Timely guess. I roughly implemented it in my experimental branch.
- Namespace (2/15) Apr 04 2013 That works well. Thanks for your efforts.
- Dicebot (7/22) Apr 04 2013 Well, I doubt there are that many native speakers here which will
- kenji hara (20/42) Apr 04 2013 I also think writing DIP would be better.
- Zach the Mystic (47/73) Apr 04 2013 My argument would be that 'scope ref' and '@temp ref' are two
- Dicebot (7/9) Apr 05 2013 Btw, Kenji, what do you think about redefining "in" to "const
- Namespace (6/15) Apr 05 2013 To change "in" from "const scope" to "const scope ref" is IMO a
- Dicebot (12/29) Apr 05 2013 How so? It does not break anything, as all "const scope" cases
- Namespace (7/15) Apr 05 2013 What I meant was simply, that users which are using already "in
- Dicebot (12/27) Apr 05 2013 I am surprised to hear that redundant storage classes are
- Namespace (5/16) Apr 05 2013 I like it also but was afraid that it could break user code. 'in
- kenji hara (6/24) Apr 05 2013 I also think that we should not change current `in` meaning.
- Zach the Mystic (20/24) Apr 04 2013 Perhaps they should, but at least I will give the use case I was
- Dicebot (10/15) Apr 05 2013 This is exactly type of code I consider to be bad style and want
- Zach the Mystic (92/108) Apr 06 2013 It may be bad style. (I don't know if it's bad style.) But there
- Dicebot (5/6) Apr 06 2013 Ye, I know it and I hate DIP25. It tries to limit references to
- Namespace (14/64) Apr 04 2013 As far as I know Andrei works on DIP25 and as far as I know from
- Zach the Mystic (2/4) Apr 03 2013 Hot stuff!
- kenji hara (5/10) Apr 02 2013 I think 'scope ref' is better.
- Benjamin Thaut (7/20) Mar 30 2013 No I highly appreciate it, that you are trying to solve the problem. The...
- Namespace (17/25) Mar 30 2013 That's nice to hear. I was afraid I would be too intrusive on
- Zach the Mystic (9/26) Mar 31 2013 It's esoteric, which is bad, but concise, which is good. I think
- Zach the Mystic (3/30) Mar 30 2013 Although adding new keywords is not smiled upon at this point, it
- Zach the Mystic (7/28) Mar 31 2013 Just a technical point, I believe your use of the term "property"
- Zach the Mystic (4/11) Mar 31 2013 To be even more precise, some built-in attributes, such as 'ref',
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
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
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
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
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
Personally yes, I prefer ref more. But you are right that it's not nice to be an annotation.
Mar 30 2013
Am 30.03.2013 11:12, schrieb Minas Mina:On Saturday, 30 March 2013 at 09:17:17 UTC, Namespace wrote:I have to agree on that. My first impression was that ref& is equal to c++11 && Kind Regards Benjamin ThautAnd 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
I have to agree on that. My first impression was that ref& is equal to c++11 && Kind Regards Benjamin ThautOk, 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
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
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
On Tuesday, 2 April 2013 at 15:08:20 UTC, Namespace wrote:On Saturday, 30 March 2013 at 12:00:32 UTC, Namespace wrote:' 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.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?
Apr 02 2013
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:s/ref int b/ref int a/On Saturday, 30 March 2013 at 12:00:32 UTC, Namespace wrote:' 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));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?
Apr 02 2013
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
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
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
On Wednesday, 3 April 2013 at 18:06:36 UTC, Dicebot wrote:On Wednesday, 3 April 2013 at 17:48:54 UTC, Namespace wrote:So you were against the introduction of ravalue references or do you just have a problem with the syntax?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
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
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
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
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 globals/*func/&func/
Apr 03 2013
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
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
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
On Thursday, 4 April 2013 at 14:43:26 UTC, Namespace wrote:On Thursday, 4 April 2013 at 07:52:51 UTC, Dicebot wrote: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.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
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
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
On Thursday, 4 April 2013 at 16:31:06 UTC, kenji hara wrote:2013/4/5 Namespace <rswhite4 googlemail.com>That works well. Thanks for your efforts.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
On Thursday, 4 April 2013 at 16:21:50 UTC, Namespace wrote: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.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
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
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
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
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: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.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
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 HaraMy 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
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
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: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.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
On Friday, 5 April 2013 at 08:35:03 UTC, Namespace wrote:On Friday, 5 April 2013 at 07:48:38 UTC, Dicebot 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. 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.On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote: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.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
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
On Friday, 5 April 2013 at 08:57:35 UTC, Namespace wrote: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.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. ;)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 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
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/3ef7a084Sorry 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
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 anerror 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
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
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
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: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.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.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
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
'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
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
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
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 know Jonathan was strict against it, or not? But that sounds and looks nice and would be very easy to implement.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
My try for scope ref/in ref: https://github.com/Dgame/dmd/tree/in_ref
Apr 02 2013
Am 30.03.2013 12:04, schrieb Namespace: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 ThautI have to agree on that. My first impression was that ref& is equal to c++11 && Kind Regards Benjamin ThautOk, 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
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 ThautThat'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
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
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/rvalueRefTo 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
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/rvalueRefI 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
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/rvalueRef2Since 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
On Saturday, 30 March 2013 at 13:07:44 UTC, Benjamin Thaut wrote:Am 30.03.2013 12:04, schrieb Namespace:Although adding new keywords is not smiled upon at this point, it might actually be worth it in this case.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 ThautI have to agree on that. My first impression was that ref& is equal to c++11 && Kind Regards Benjamin ThautOk, 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
On Saturday, 30 March 2013 at 09:17:17 UTC, Namespace 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.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&.
Mar 31 2013
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