www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Multiple return value as requirements for safety and performance

reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
One good thing for safety and CTFE is allow multiple return 
value. In combination with `auto ref` it is _very_ powerful:

----
auto ref front()
{
   // Returns 2 values, each value is returned by reference if 
possible
   return (a.front, b.front);
}
----

Mir libs will use pointers for now. This is one of reasons why 
`zip` is slow.
The new feature also significantly extends std.range and 
std.algorithm functionality.

This thread was forked from
http://forum.dlang.org/post/acdwfbirvoxzrsfyltqd forum.dlang.org

I am not good in DIPs and hope someone is interested in this 
feature too
Dec 20 2016
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Tuesday, 20 December 2016 at 13:47:50 UTC, Ilya Yaroshenko 
wrote:
 One good thing for safety and CTFE is allow multiple return 
 value. In combination with `auto ref` it is _very_ powerful:

 ----
 auto ref front()
 {
   // Returns 2 values, each value is returned by reference if 
 possible
   return (a.front, b.front);
 }
 ----

 Mir libs will use pointers for now. This is one of reasons why 
 `zip` is slow.
 The new feature also significantly extends std.range and 
 std.algorithm functionality.

 This thread was forked from
 http://forum.dlang.org/post/acdwfbirvoxzrsfyltqd forum.dlang.org

 I am not good in DIPs and hope someone is interested in this 
 feature too
Do tuples work for this?
Dec 20 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 14:04:26 UTC, Nicholas Wilson 
wrote:
 On Tuesday, 20 December 2016 at 13:47:50 UTC, Ilya Yaroshenko 
 wrote:
 One good thing for safety and CTFE is allow multiple return 
 value. In combination with `auto ref` it is _very_ powerful:

 ----
 auto ref front()
 {
   // Returns 2 values, each value is returned by reference if 
 possible
   return (a.front, b.front);
 }
 ----

 Mir libs will use pointers for now. This is one of reasons why 
 `zip` is slow.
 The new feature also significantly extends std.range and 
 std.algorithm functionality.

 This thread was forked from
 http://forum.dlang.org/post/acdwfbirvoxzrsfyltqd forum.dlang.org

 I am not good in DIPs and hope someone is interested in this 
 feature too
Do tuples work for this?
No, tuples stores either value or pointer. If it stores pointer then it is not safe and it is not CTFE.
Dec 20 2016
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/20/2016 6:08 AM, Ilya Yaroshenko wrote:
 No, tuples stores either value or pointer. If it stores pointer then it is not
 safe and it is not CTFE.
You can make it safe by using an array rather than a pointer.
Dec 20 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 16:34:04 UTC, Walter Bright wrote:
 On 12/20/2016 6:08 AM, Ilya Yaroshenko wrote:
 No, tuples stores either value or pointer. If it stores 
 pointer then it is not
 safe and it is not CTFE.
You can make it safe by using an array rather than a pointer.
Ranges a and b may not be arrays. They just have Range API and return front by reference.How this can be handled for CTFE, safe code? Would the solution be fast?
Dec 20 2016
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 20 December 2016 at 16:57:34 UTC, Ilya Yaroshenko 
wrote:
 On Tuesday, 20 December 2016 at 16:34:04 UTC, Walter Bright 
 wrote:
 On 12/20/2016 6:08 AM, Ilya Yaroshenko wrote:
 No, tuples stores either value or pointer. If it stores 
 pointer then it is not
 safe and it is not CTFE.
You can make it safe by using an array rather than a pointer.
Ranges a and b may not be arrays. They just have Range API and return front by reference.How this can be handled for CTFE, safe code? Would the solution be fast?
What are you even talking about ? Making a Tuple is fine. Pointers can also be perfectly safe and CTFEable if you do not try to mess with them. For a Range you have to pass some form of context regardless so there will always be a quite small price to be payed. -- Performance is not something you just get. Work is required if you want good performance and no library or language is going to change that.
Dec 20 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 17:05:03 UTC, Stefan Koch wrote:
 On Tuesday, 20 December 2016 at 16:57:34 UTC, Ilya Yaroshenko 
 wrote:
 On Tuesday, 20 December 2016 at 16:34:04 UTC, Walter Bright 
 wrote:
 On 12/20/2016 6:08 AM, Ilya Yaroshenko wrote:
 No, tuples stores either value or pointer. If it stores 
 pointer then it is not
 safe and it is not CTFE.
You can make it safe by using an array rather than a pointer.
Ranges a and b may not be arrays. They just have Range API and return front by reference.How this can be handled for CTFE, safe code? Would the solution be fast?
What are you even talking about ? Making a Tuple is fine. Pointers can also be perfectly safe and CTFEable if you do not
Are they already CTFEable? I have not seen an anounce, sorry
Dec 20 2016
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 20 December 2016 at 17:15:53 UTC, Ilya Yaroshenko 
wrote:
 Are they already CTFEable? I have not seen an anounce, sorry
They have been for years now. Of course only pointers from a CTFE context are valid at ctfe. The new engine will support them as well, (as it will eventually support everything with the exception of 80bit reals)
Dec 20 2016
next sibling parent Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 17:28:49 UTC, Stefan Koch wrote:
 On Tuesday, 20 December 2016 at 17:15:53 UTC, Ilya Yaroshenko 
 wrote:
 Are they already CTFEable? I have not seen an anounce, sorry
They have been for years now. Of course only pointers from a CTFE context are valid at ctfe. The new engine will support them as well, (as it will eventually support everything with the exception of 80bit reals)
Thanks! Sorry for the noise!
Dec 20 2016
prev sibling parent Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 17:28:49 UTC, Stefan Koch wrote:
 On Tuesday, 20 December 2016 at 17:15:53 UTC, Ilya Yaroshenko 
 wrote:
 Are they already CTFEable? I have not seen an anounce, sorry
They have been for years now. Of course only pointers from a CTFE context are valid at ctfe. The new engine will support them as well, (as it will eventually support everything with the exception of 80bit reals)
`Tuple` + pointers do not help. Multiple auto ref values are required anyway. The reason is that tuple.expand analog can not pass something by reference from original ranges (it has pointers and values). Multiple auto ref values are required to have syntax like this: zip(a, b).each!swap; I know that we have swapRanges, but this is not solution for Mir because Mir should have small API without hundreds of trivial functions like in Armadillo. Thanks, Ilya
Dec 24 2016
prev sibling next sibling parent Anonymouse <asdf asdf.net> writes:
On Tuesday, 20 December 2016 at 13:47:50 UTC, Ilya Yaroshenko 
wrote:
 One good thing for safety and CTFE is allow multiple return 
 value. In combination with `auto ref` it is _very_ powerful:

 ----
 auto ref front()
 {
   // Returns 2 values, each value is returned by reference if 
 possible
   return (a.front, b.front);
 }
Nested Voldemort structs? Horcruxified, to work around the symbol name length explosion. I always imagined allowing for multiple values (in multiple fields) was part of the point behind them. For instance, consider the several discrete pieces of data you get from the Result of std.regex matching. (Not all of it is via opIndex.)
Dec 20 2016
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/20/2016 5:47 AM, Ilya Yaroshenko wrote:
 One good thing for safety and CTFE is allow multiple return value. In
 combination with `auto ref` it is _very_ powerful:

 ----
 auto ref front()
 {
   // Returns 2 values, each value is returned by reference if possible
   return (a.front, b.front);
 }
 ----
auto ref front() { return tuple(a.front, b.front); }
Dec 20 2016
next sibling parent Daniel =?iso-8859-1?b?S2964Ws=?= via Digitalmars-d writes:
Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> napsal=20
=C3=9At, pro 20, 2016 v 3=E2=88=B647 :
 On 12/20/2016 5:47 AM, Ilya Yaroshenko wrote:
 One good thing for safety and CTFE is allow multiple return value. In
 combination with `auto ref` it is _very_ powerful:
=20
 ----
 auto ref front()
 {
   // Returns 2 values, each value is returned by reference if=20
 possible
   return (a.front, b.front);
 }
 ----
=20 =20 auto ref front() { return tuple(a.front, b.front); }
https://github.com/dlang/phobos/blob/master/std/typecons.d#L1686 I do not see any auto ref at code, so I do not belive this will work =
Dec 20 2016
prev sibling parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 14:47:28 UTC, Walter Bright wrote:
 On 12/20/2016 5:47 AM, Ilya Yaroshenko wrote:
 One good thing for safety and CTFE is allow multiple return 
 value. In
 combination with `auto ref` it is _very_ powerful:

 ----
 auto ref front()
 {
   // Returns 2 values, each value is returned by reference if 
 possible
   return (a.front, b.front);
 }
 ----
auto ref front() { return tuple(a.front, b.front); }
Tuples can not work with auto ref. This is a reason for this thread. Proof: ----- import std.typecons: tuple; int[] a = [1,2,3]; int[] b = [1,2,3]; auto ref front() { import std.range: front; return tuple(a.front, b.front); } void main() { front()[0] = 1000; import std.stdio; writeln(front()[0]); } ----- Output: 1 ----- As you can see the output should be 1000, but it is 1. It can be solved with pointers, and Mir will have their own tuples which use pointers. But it is not good because: 1. Pointers are not CTFE-able. 2. Pointers are not safe.
Dec 20 2016
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Tuesday, 20 December 2016 at 14:56:37 UTC, Ilya Yaroshenko 
wrote:

 As you can see the output should be 1000, but it is 1.
I was a little confused by what you meant, but the following main is a little more obvious to me void main() { auto c = front(); c[0] = 1000; import std.stdio; writeln(c[0]); //prints 1000 writeln(a[0]); //prints 1 }
Dec 20 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 15:36:27 UTC, jmh530 wrote:
 On Tuesday, 20 December 2016 at 14:56:37 UTC, Ilya Yaroshenko 
 wrote:

 As you can see the output should be 1000, but it is 1.
I was a little confused by what you meant, but the following main is a little more obvious to me void main() { auto c = front(); c[0] = 1000; import std.stdio; writeln(c[0]); //prints 1000 writeln(a[0]); //prints 1 }
c is value. You can modify it with tuples. Tuples can be returned. This thread is about mutiple values returned by _reference_. Tuples can not do it, only pointers, but they are not ctfeable and safe
Dec 20 2016
next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Tuesday, 20 December 2016 at 15:42:52 UTC, Ilya Yaroshenko 
wrote:
 This thread is about mutiple values returned by _reference_. 
 Tuples can not do it, only pointers, but they are not ctfeable 
 and safe
Do pointers worsen performance aswell? Even when using LDC?
Dec 20 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 15:50:03 UTC, Nordlöw wrote:
 On Tuesday, 20 December 2016 at 15:42:52 UTC, Ilya Yaroshenko 
 wrote:
 This thread is about mutiple values returned by _reference_. 
 Tuples can not do it, only pointers, but they are not ctfeable 
 and safe
Do pointers worsen performance aswell? Even when using LDC?
Tuples of pointers are faster then tuples of values. Hypothetical tuples of references have the same performance as tuples of references.
Dec 20 2016
parent Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Tuesday, 20 December 2016 at 16:06:49 UTC, Ilya Yaroshenko 
wrote:
 On Tuesday, 20 December 2016 at 15:50:03 UTC, Nordlöw wrote:
 On Tuesday, 20 December 2016 at 15:42:52 UTC, Ilya Yaroshenko 
 wrote:
 This thread is about mutiple values returned by _reference_. 
 Tuples can not do it, only pointers, but they are not 
 ctfeable and safe
Do pointers worsen performance aswell? Even when using LDC?
Tuples of pointers are faster then tuples of values. Hypothetical tuples of references have the same performance as tuples of references.
EDIT: as tuples of pointers.
Dec 20 2016
prev sibling parent pineapple <meapineapple gmail.com> writes:
On Tuesday, 20 December 2016 at 15:42:52 UTC, Ilya Yaroshenko 
wrote:
 This thread is about mutiple values returned by _reference_. 
 Tuples can not do it, only pointers, but they are not ctfeable 
 and safe
The way to make this useful, if I'm understanding correctly, would not be a more concise way to express `return tuple(a, b);` where `tuple` is the function defined in typecons, but to make expressions like `return tuple(a, b).expand;` become valid and using a syntax like `return (a, b);` to represent them. (For which I would suggest also making the parentheses optional, but that's minutiae.) The syntax for assigning the returned values would likely not look like `auto x = {return (a, b);}(); assert(x[0] == a);`. This because `x` would not be a tuple in the sense of std.typecons.Tuple, but a tuple in the sense of what you get when you `expand` such a type. The assignment syntax should be more like `auto x, y = {return (a, b);}(); assert(x == a);`. Where the intent is to store the two values in the same variable, I expect a struct like Tuple should continue to be used. And because in these examples `a` and `b` would not be members of a tuple struct, it would become possible to return some or all of them by reference, as can currently be done for a single returned value.
Dec 20 2016
prev sibling next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Tuesday, 20 December 2016 at 13:47:50 UTC, Ilya Yaroshenko 
wrote:
 One good thing for safety and CTFE is allow multiple return 
 value. In combination with `auto ref` it is _very_ powerful:

 auto ref front()
 {
   // Returns 2 values, each value is returned by reference if 
 possible
   return (a.front, b.front);
 }
I'd love to have this syntax aswell.
 I am not good in DIPs and hope someone is interested in this 
 feature too
DIP-32 has been dormant since 2013. I've been waiting for builtin tuples ever since I started using D. I believe the community agrees upon that we want the Python-style syntax to be used. But in order for this to be integrated we must wait out the deprecation of the C-inherited comma expression to become an error. Correct me if I'm wrong. See: - https://wiki.dlang.org/DIP32 - http://forum.dlang.org/post/kj44fs$2iil$1 digitalmars.com Didn't Kenji Hara implement one of his proposals in DMD?...I might remember wrong.
Dec 20 2016
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Tuesday, 20 December 2016 at 15:40:57 UTC, Nordlöw wrote:
 DIP-32 has been dormant since 2013. I've been waiting for 
 builtin tuples ever since I started using D.
I wonder if it might be possible to add the tuple syntax incrementally into DMD? It's always easier to approve something less complex. Could the comma expression be contextually removed? Specifically in return expressions as discussed initially in this post?
Dec 20 2016
parent reply Brad Anderson <eco gnuk.net> writes:
On Tuesday, 20 December 2016 at 15:47:38 UTC, Nordlöw wrote:
 On Tuesday, 20 December 2016 at 15:40:57 UTC, Nordlöw wrote:
 DIP-32 has been dormant since 2013. I've been waiting for 
 builtin tuples ever since I started using D.
I wonder if it might be possible to add the tuple syntax incrementally into DMD? It's always easier to approve something less complex. Could the comma expression be contextually removed? Specifically in return expressions as discussed initially in this post?
Back in May a change was introduced to issue a deprecation message for uses of the comma operator outside of a for statement. Not sure which dmd version it got introduced into but it's surely in there by now. https://github.com/dlang/dmd/pull/5737
Dec 20 2016
parent Nick Treleaven <nick geany.org> writes:
On Tuesday, 20 December 2016 at 18:51:05 UTC, Brad Anderson wrote:
 Could the comma expression be contextually removed? 
 Specifically in return expressions as discussed initially in 
 this post?
Back in May a change was introduced to issue a deprecation message for uses of the comma operator outside of a for statement.
Not quite, the comma expression can be used anywhere so long as the result is not used. http://dlang.org/changelog/2.072.0.html#deprecated_commaexp
Jan 02 2017
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 20.12.2016 14:47, Ilya Yaroshenko wrote:
 One good thing for safety and CTFE is allow multiple return value. In
 combination with `auto ref` it is _very_ powerful:

 ----
 auto ref front()
 {
   // Returns 2 values, each value is returned by reference if possible
   return (a.front, b.front);
 }
 ----
 ...
There is already syntax for something similar to this (for the auto-expanding version). auto ref seq(T...)(return auto ref T args){ return args; } auto ref front(){ return seq(a.front, b.front); } However, DMD will reject this at the moment.
 Mir libs will use pointers for now. This is one of reasons why `zip` is
 slow.
 The new feature also significantly extends std.range and std.algorithm
 functionality.

 This thread was forked from
 http://forum.dlang.org/post/acdwfbirvoxzrsfyltqd forum.dlang.org

 I am not good in DIPs and hope someone is interested in this feature too
This will likely be added as soon as the comma operator has finished its deprecation cycle. (I might give this a shot after finally polishing the static foreach DIP.)
Dec 20 2016