www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Returning multiple arrays from function - struct or byref the only

reply "Laeeth Isharc" <laeethnospam spammenot_laeeth.com> writes:
Hi.

I have to write a bunch of functions that operate on input arrays 
to return multiple output arrays.

In case helpful the inputs are price bars or economic data points 
(datetime, ohlc) and the outputs are nx1 arrays (I won't say 
vectors) of doubles or structs.

What is the best way to return multiple arrays in this kind of 
situation.  In Python I returned a tuple of numpy arrays, and the 
C way would be to pass a pointer to the return destinations, and 
I guess I could do the same in a D way by passing by ref not 
value).

I see that I can return a struct containing dynamic arrays, and 
return it (by value of course).  I have read the forum discussion 
a while back over how to return multiple values, and tried using 
tuples.  I don't see that I can return a tuple of arrays - am I 
missing something?

Here is a simple case.  Can I do better ?

Thanks.


import std.typecons;
import std.stdio;

struct RetStruct
{
	double[] a;
	double[] b;
}

RetStruct myfunction(double x)
{
	RetStruct s;
	double[] a,b;
	a~=x+1.0;
	a~=x+9.0;
	b~=x+2.0;
	b~=x+11.0;
	s.a=a;
	s.b=b;
	return s;
}

void main()
{
	writefln("%s",myfunction(99.0));
}
Oct 15 2014
next sibling parent "Laeeth Isharc" <laeethnospam spammenot_laeeth.com> writes:
Here is byref:


import std.typecons;
import std.stdio;

void myfunction(double x, ref double[] a, ref double[] b)
{
	a~=x+1.0;
	a~=x+9.0;
	b~=x+2.0;
	b~=x+11.0;
	return;
}

void main()
{
	double[] a;
	double[] b;
	myfunction(99.0,a,b);
	writefln("%s %s",a,b);
}
Oct 15 2014
prev sibling next sibling parent "Meta" <jared771 gmail.com> writes:
On Wednesday, 15 October 2014 at 16:48:24 UTC, Laeeth Isharc 
wrote:
 Hi.

 I have to write a bunch of functions that operate on input 
 arrays to return multiple output arrays.

 In case helpful the inputs are price bars or economic data 
 points (datetime, ohlc) and the outputs are nx1 arrays (I won't 
 say vectors) of doubles or structs.

 What is the best way to return multiple arrays in this kind of 
 situation.  In Python I returned a tuple of numpy arrays, and 
 the C way would be to pass a pointer to the return 
 destinations, and I guess I could do the same in a D way by 
 passing by ref not value).

 I see that I can return a struct containing dynamic arrays, and 
 return it (by value of course).  I have read the forum 
 discussion a while back over how to return multiple values, and 
 tried using tuples.  I don't see that I can return a tuple of 
 arrays - am I missing something?

 Here is a simple case.  Can I do better ?

 Thanks.


 import std.typecons;
 import std.stdio;

 struct RetStruct
 {
 	double[] a;
 	double[] b;
 }

 RetStruct myfunction(double x)
 {
 	RetStruct s;
 	double[] a,b;
 	a~=x+1.0;
 	a~=x+9.0;
 	b~=x+2.0;
 	b~=x+11.0;
 	s.a=a;
 	s.b=b;
 	return s;
 }

 void main()
 {
 	writefln("%s",myfunction(99.0));
 }
You could also return an std.typecons.Tuple containing both
Oct 15 2014
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 10/15/2014 09:48 AM, Laeeth Isharc wrote:

 struct RetStruct
 {
      double[] a;
      double[] b;
 }

 RetStruct myfunction(double x)
That's my preference. Tuples would work as well but they have two minor issues for me: - Unlike a struct, the members are anonymous. (Yes, tuples members can have names as well but not when returning or creating conveniently by 'return tuple(a, b)'.) - Unlike Python, there is no automatic tuple expansion so one has to refer to the members as result[0] and result[1], which is less readable than struct members. (Yes, there is some support for tuple expansion e.g. in foreach but it has some issues with the automatic foreach loop counter.) Summary: I return by struct. :) Ali
Oct 15 2014
next sibling parent "Laeeth Isharc" <Laeeth.nospam nospam-laeeth.com> writes:
Thanks for the thoughts Meta and Ali.

Laeeth.


On Wednesday, 15 October 2014 at 17:56:06 UTC, Ali Çehreli wrote:
 On 10/15/2014 09:48 AM, Laeeth Isharc wrote:

 struct RetStruct
 {
      double[] a;
      double[] b;
 }

 RetStruct myfunction(double x)
That's my preference. Tuples would work as well but they have two minor issues for me: - Unlike a struct, the members are anonymous. (Yes, tuples members can have names as well but not when returning or creating conveniently by 'return tuple(a, b)'.) - Unlike Python, there is no automatic tuple expansion so one has to refer to the members as result[0] and result[1], which is less readable than struct members. (Yes, there is some support for tuple expansion e.g. in foreach but it has some issues with the automatic foreach loop counter.) Summary: I return by struct. :) Ali
Oct 18 2014
prev sibling parent reply "Meta" <jared771 gmail.com> writes:
On Wednesday, 15 October 2014 at 17:56:06 UTC, Ali Çehreli wrote:
 - Unlike a struct, the members are anonymous. (Yes, tuples 
 members can have names as well but not when returning or 
 creating conveniently by 'return tuple(a, b)'.)
This works, but I agree it is a bit obscure (you may want to add it to your book if it's not already there): import std.typecons; Tuple!(int[], "left", int[], "right") foo(int n, int m) { return typeof(return)(new int[](n), new int[](m)); } void main() { auto res = foo(2, 3); assert(res.left.length == 2); assert(res.right.length == 3); } The problem is that D does not allow implicit conversions when returning results from a function. Tuple!(int[], int[]) is implicitly castable to Tuple!(int[], "left", int[], "right"), but you cannot return the result of tuple(new int[](n), new int[](m)) from foo(), as they are technically still different types, which would require an implicit conversion. This is (IMO) a problem; it's extremely annoying when trying to use std.typecons.Algebraic.
Oct 18 2014
parent "Meta" <jared771 gmail.com> writes:
On Saturday, 18 October 2014 at 14:56:06 UTC, Meta wrote:
 The problem is that D does not allow implicit conversions when 
 returning results from a function.
"Implicit conversion" is not correct. I meant "implicit contruction".
Oct 18 2014