digitalmars.D.bugs - [Issue 1869] New: Semantically returning an array from a funciton is difficult
- d-bugmail puremagic.com (33/33) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (7/10) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (10/20) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (13/13) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (20/34) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (7/7) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- Robert Fraser (3/16) Feb 25 2008 A cast is _never_ a viable solution. A cast says "undefined
- d-bugmail puremagic.com (18/18) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- Derek Parnell (11/23) Feb 25 2008 Why? Or in other words, define "The right thing" and "manipulate". I'm n...
- d-bugmail puremagic.com (7/7) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- Janice Caron (34/37) Feb 25 2008 int[] f()
- BCS (2/10) Feb 26 2008 None of those do quite what I want (see comment #18 down at the bottom)
- d-bugmail puremagic.com (10/15) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (6/6) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (5/8) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (14/14) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (17/22) Feb 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (14/14) Feb 26 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (9/23) Feb 26 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (9/16) Feb 26 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- Bill Baxter (6/27) Feb 26 2008 digitalmars.d.learn, in fact.
- d-bugmail puremagic.com (15/20) Feb 26 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (18/31) Feb 26 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1869
- d-bugmail puremagic.com (12/12) Nov 26 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1869
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. --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 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. --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869The reason that static arrays can't be returned is that they are pointers to local variables. That is in reference to this code: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? --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.
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 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? --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869Hm. 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?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. --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 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); --
Feb 25 2008
d-bugmail puremagic.com wrote:http://d.puremagic.com/issues/show_bug.cgi?id=1869 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".
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 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 --
Feb 25 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 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 requestedThank 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
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 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) --
Feb 25 2008
On 26/02/2008, d-bugmail puremagic.com <d-bugmail puremagic.com> wrote: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).int[] f() { return [1,2,3,4].dup; } or int[] f() { auto r = new int[4]; /* assign r's elements */ return r; } If you need to prove that the array is exactly four bytes long, do int[] f() out(r) { assert(r.length == 4); } body { ... } If you really, really need to return by value, do struct A(T, int N) { T[N] a; } A!(int,4) f() { A!(int,4) r; /* assign r.a */ return r; } Hopefully, one of these will suit your needs
Feb 25 2008
Reply to Janice,On 26/02/2008, d-bugmail puremagic.com <d-bugmail puremagic.com> wrote: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).Hopefully, one of these will suit your needs
Feb 26 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869but 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)I don't understand. Doesn't this work? int[4]* foo() { static int[4] x; return &x; } ? --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 I don't think so; that is a pointer to a pointer to a string of 4 ints (or a string of 4 pointers to ints, I can never parse those by eye) it has one too many levels of indirection. --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869I don't think so; that is a pointer to a pointer to a string of 4 ints (or a string of 4 pointers to ints, I can never parse those by eye) it has one too many levels of indirection.I'm completely lost. float[4]* has exactly one level of indirection. --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 traditionally arrays are worked by pointer math. While the array is a segment of memory, its manifestation in the code is as a pointer. So "i[2]" takes a pointer adds an offset of 2 and does the IO. From this "int[4]*" will be a pointer to something that can be used like a an array, e.i. it will be a pointer to a somewhat hidden pointer. IIRC back in C, the compiler didn't make any distinction between an array name and a pointer. In fact they don't worry about what is the array and what is the index. This actually works (or did at one point): int i[10]; 7[i] = 4; --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869traditionally arrays are worked by pointer math. While the array is a segment of memory, its manifestation in the code is as a pointer. So "i[2]" takes a pointer adds an offset of 2 and does the IO. From this "int[4]*" will be a pointer to something that can be used like a an array, e.i. it will be a pointer to a somewhat hidden pointer.That is incorrect. There is no hidden pointer and no extra indirection. There is a confusion somewhere along the way, so please let me give an example: void main() { int a[4]; int[4]* b = &a; a[1] = 2; (*b)[1] = 3; } Say that the four ints in a start at address 1000. Then a is an immutable pointer with value 1000. Also, b is a rebindable pointer with value 1000. Dereferencing b takes you straight to the first element of a, not to some hidden pointer that in turn takes you to the first element of a. --
Feb 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 Thanks for the comments, it's more or less as I suspected. The ways of returning an arrays pointed out by Janice Caron and others seem to feel like a 'workaround' to me. I don't quite understand why the code below does not (or cannot work). The pass by reference semantics of arrays don't have to apply for function return do they? It might create a special case though I suppose. int[4][4] f() { int a[4][4]; return a; } --
Feb 26 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869Thanks for the comments, it's more or less as I suspected. The ways of returning an arrays pointed out by Janice Caron and others seem to feel like a 'workaround' to me. I don't quite understand why the code below does not (or cannot work). The pass by reference semantics of arrays don't have to apply for function return do they? It might create a special case though I suppose. int[4][4] f() { int a[4][4]; return a; }This will work. We'll also pass arrays in by value, and will bind literals to dynamically-sized arrays. In response to Derek: this is the "right thing" because every type in D has the same copy semantics whether it sits inside a struct or not. Every type... except statically-sized arrays. --
Feb 26 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 ...This will work. We'll also pass arrays in by value, and will bind literals to dynamically-sized arrays. In response to Derek: this is the "right thing" because every type in D has the same copy semantics whether it sits inside a struct or not. Every type... except statically-sized arrays.Ok, I understand now. Seems good. This change will be in DMD 2.x at some future point. I should of posted to digitalmars.d for this sort of thing instead of raising this as a bug shouldn't I? --
Feb 26 2008
d-bugmail puremagic.com wrote:http://d.puremagic.com/issues/show_bug.cgi?id=1869 ...digitalmars.d.learn, in fact. However, you wouldn't have gotten this useful feedback from Andrei over there, because he doesn't read (or at least reply to) the NG's. So it's hard to say you did the wrong thing here. --bbThis will work. We'll also pass arrays in by value, and will bind literals to dynamically-sized arrays. In response to Derek: this is the "right thing" because every type in D has the same copy semantics whether it sits inside a struct or not. Every type... except statically-sized arrays.Ok, I understand now. Seems good. This change will be in DMD 2.x at some future point. I should of posted to digitalmars.d for this sort of thing instead of raising this as a bug shouldn't I?
Feb 26 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869That is incorrect. There is no hidden pointer and no extra indirection. There is a confusion somewhere along the way, so please let me give an example:are you talking C or D? I could have sworn that in C a "pointer to a fixed size array" (e.i. double indirection) was written as "int[4]*". If it isn't, how is it written? Oh. I think I just figured it out!: int[4] a; int[4]* i = &a; i points to the same point as a but has a different type *i is the same pointer as i but with the type of a and **i is the content. OK what I want to do is return *(&a), a type that is the same as "a" but is mutable. p.s. Darn I should check the by line before I post --
Feb 26 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 andrei metalanguage.com changed: What |Removed |Added ---------------------------------------------------------------------------- Severity|normal |enhancementare you talking C or D?Both.I could have sworn that in C a "pointer to a fixed size array" (e.i. double indirection) was written as "int[4]*". If it isn't, how is it written?It is written like that, and there is no double indirection.Oh. I think I just figured it out!: int[4] a; int[4]* i = &a; i points to the same point as a but has a different type *i is the same pointer as i but with the type of a and **i is the content.That is correct.OK what I want to do is return *(&a), a type that is the same as "a" but is mutable.You'd need to return a reference to a fixed-size array, which in C does not exist, in C++ is spelled int[4]&, and in D is spelled ref int[4] but so far only applies to function arguments. Note that neither would be mutable, so you seem to want something that is physically possible but can't be expressed in either of the three languages. I'm keeping this bug report as a request for returning arrays by value, but I guess it's duplicated with a couple others. --
Feb 26 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1869 Don <clugdbug yahoo.com.au> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED CC| |clugdbug yahoo.com.au Resolution| |FIXED Fixed DMD2.036: fixed-length arrays are now passed by value. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2009