Jump to page: 1 2 3
Thread overview
[Issue 1869] New: Semantically returning an array from a funciton is difficult
Feb 25, 2008
d-bugmail
Feb 25, 2008
d-bugmail
Feb 25, 2008
d-bugmail
Feb 25, 2008
d-bugmail
Feb 25, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Feb 26, 2008
Robert Fraser
Feb 26, 2008
d-bugmail
Feb 26, 2008
Derek Parnell
Feb 26, 2008
d-bugmail
Feb 26, 2008
Janice Caron
Feb 26, 2008
BCS
Feb 26, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Feb 26, 2008
Bill Baxter
Feb 26, 2008
d-bugmail
Feb 26, 2008
d-bugmail
Nov 26, 2009
Don
February 25, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869

           Summary: Semantically returning an array from a funciton is
                    difficult
           Product: D
           Version: 1.026
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Keywords: spec
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: jason@spashett.com


It is difficult to 'return' an array from a function. Static arrays cannot be returned, presumably because arrays are akin to full class objects. This sometimes  is a bit inconvenient when, for example one would like to assign to a static array by calling a function.

In contrast structs can be returned from a function easily, and in fact to return an array one can wrap it in a struct. Other ways may include the use of boxing, or returning a dynamic array, which becomes more complicated if it is multi-dimensional.

Currently this method seems the best solution, but requires a persistent object allocation as opposed to using the stack (as in structs presumably):

/* Assume matrix is a class member, or static */
float[4][4] * toFloatArray4x4()
{
        return &matrix;
}

float v[4][4] = *m1.toFloatArray4x4();

Obviously arrays can also be passed in as parameters, but this denies one the functional return like semantic which can often be useful.


-- 

February 25, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869





------- Comment #1 from shro8822@vandals.uidaho.edu  2008-02-25 15:46 -------
The reason that static arrays can't be returned is that they are pointers to local variables. That is in reference to this code:
>int[10] a;
>return a;

however IIRC you can have a function return type int[4]:
>int[4] fn(int i, int[4][4] j) { return j[i]; }

I guess I'm not realy understanding what your concern is.


-- 

February 25, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869





------- Comment #2 from jason@spashett.com  2008-02-25 17:03 -------
(In reply to comment #1)
> The reason that static arrays can't be returned is that they are pointers to local variables. That is in reference to this code:
> >int[10] a;
> >return a;
> 
> however IIRC you can have a function return type int[4]:
> >int[4] fn(int i, int[4][4] j) { return j[i]; }
> 
> I guess I'm not realy understanding what your concern is.
> 

Is this new in D 2.x ?

I get main.d(813): Error: functions cannot return static array int[4u]
with your example.

My example is for a two dimensional array, which up until fairly recently was hard to initialise from a static array (until recently dmd 2.0 changelog)

Is it the case therefore that dmd 2.x supports returning of static arrays?


-- 

February 25, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869





------- Comment #3 from shro8822@vandals.uidaho.edu  2008-02-25 17:21 -------
Hm. I'm almost sure I've done that before. And no, I use 1.0.

If my examples don't work, I think it should be considered a bug (in the design if not the implementation).

On seconds though, you point out that a struct can be returned. This will actually be done by value (returning a struct with an int[4] inside will copy 4*int.sizeof bytes) D might be interpreting returning int[4] in that way and refusing (that could get real nasty with some template code computing n=1e6 or some such).

If that is the case, why does it treat it as values on return and as references on pass?


-- 

February 25, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869





------- Comment #4 from jason@spashett.com  2008-02-25 17:47 -------
(In reply to comment #3)
> Hm. I'm almost sure I've done that before. And no, I use 1.0.
> 
> If my examples don't work, I think it should be considered a bug (in the design if not the implementation).
> 
> On seconds though, you point out that a struct can be returned. This will actually be done by value (returning a struct with an int[4] inside will copy 4*int.sizeof bytes) D might be interpreting returning int[4] in that way and refusing (that could get real nasty with some template code computing n=1e6 or some such).
> 
> If that is the case, why does it treat it as values on return and as references on pass?
> 

D is a bit like java and c# in that small intrinsic items like ints, floats are passed by value, the same is true of stucts. It's a trade off between efficiency and pass by value semantics I guess.

An array, and a class are considered largeish things and so it's assumed you will want them to go 'though' by reference. In fact you can't pass an array by value even if you use the "in" keyword. In a way arrays work similarly in C and C++ except in those languages they are pointers and loose type information when you pass them in. The problem in D I seem to be encountering is that there is no nice, or convenient way of returning an array (the problem gets worse with multi dimensional arrays because you have to set them up and until recently in dmd 2.0 you couldn't initialize them in one go AFIK)

I don't have to return an array, but it makes what I am trying to do a bit more clumsy. For example I can't pass into (OpenGL) glMatrixMultiply an array of float[16] by simply calling matrix.toFloat16() I must use a temporary variable, which is a slight pain. Or; I can use my 'pointer workaround' which is bit of a hack.


-- 

February 26, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869





------- Comment #5 from shro8822@vandals.uidaho.edu  2008-02-25 18:06 -------
That's about like I remembered.

If you don't mind the cast...

int* foo(int[4][4] j, int i) { return &(j[i]); }
cast(int[4])foo(a,i);


-- 

February 26, 2008
d-bugmail@puremagic.com wrote:
> http://d.puremagic.com/issues/show_bug.cgi?id=1869
> 
> 
> 
> 
> 
> ------- Comment #5 from shro8822@vandals.uidaho.edu  2008-02-25 18:06 -------
> That's about like I remembered.
> 
> If you don't mind the cast...
> 
> int* foo(int[4][4] j, int i) { return &(j[i]); }
> cast(int[4])foo(a,i);

A cast is _never_ a viable solution. A cast says "undefined behavior"/"doing something the type system says I shouldn't be".
February 26, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869





------- Comment #6 from andrei@metalanguage.com  2008-02-25 18:59 -------
The right thing to do is to manipulate fixed-sized arrays by value, but there are a number of consequent issues to solve, e.g. we wouldn't like this:

writeln("Hello, world!");

to copy the actual content of the string on the stack and over to the callee. Walter is considering making all array constants bind to dynamically-sized types by default, and to statically-sized types only when explicitly requested, e.g.:

auto x = "Hello, world!" // x is string
char[$] y = "Hello, world!" // y is char[13]
char[auto] z = "Hello, world!" // z is char[13]

The syntax is not decided between y's and z's. (Only one at most will be chosen.) The former is better because you can then write:

auto[$] w = "Hello, world!" // w is invariant(char)[13]

whereas auto[auto] would look awkward.


Andrei


-- 

February 26, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869





------- Comment #7 from shro8822@vandals.uidaho.edu  2008-02-25 19:05 -------
but that still doesn't solve the base issue: I want a function to return a pointer to a chunk of memory that is 4 ints in a row (or it is that as best the compiler can tell).

(Err. I hope that is understandable)


-- 

February 26, 2008
On Tue, 26 Feb 2008 00:59:18 +0000 (UTC), d-bugmail@puremagic.com wrote:

> http://d.puremagic.com/issues/show_bug.cgi?id=1869
> 
> ------- Comment #6 from andrei@metalanguage.com  2008-02-25 18:59 -------
> The right thing to do is to manipulate fixed-sized arrays by value,

Why? Or in other words, define "The right thing" and "manipulate". I'm not disagreeing with you, just asking for clarification.

>  but there
> are a number of consequent issues to solve, e.g. we wouldn't like this:
> 
> writeln("Hello, world!");
> 
> to copy the actual content of the string on the stack and over to the callee. Walter is considering making all array constants bind to dynamically-sized types by default, and to statically-sized types only when explicitly requested

Thank goodness. I've always thought that assuming string literals are fixed length arrays was a suboptimal choice.

I like the [$] syntax too for declaring fixed length array literals.


-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
26/02/2008 12:06:37 PM
« First   ‹ Prev
1 2 3