digitalmars.D.learn - How do I pass multidimensional static arrays to functions expecting
- Andrej Mitrovic (16/16) Aug 29 2011 Take a look:
- Timon Gehr (9/25) Aug 29 2011 D does not have multidimensional dynamic arrays.
- bearophile (7/8) Aug 29 2011 Simpler:
- Timon Gehr (3/11) Aug 30 2011 And buggy. It returns slices of a local stack frame, because static
- bearophile (6/16) Aug 30 2011 q{ a[] } does the same thing as (int[] a){return a;}, both return a slic...
- Timon Gehr (9/21) Aug 30 2011 No, what they do is very different. Yours creates a new stack frame,
- bearophile (3/4) Aug 30 2011 Thank you, bye,
- Andrej Mitrovic (7/7) Aug 29 2011 Right, but I was just trying to temporarily avoid GC allocation so
- Andrej Mitrovic (12/12) Aug 29 2011 Hey btw, do you think we could use this in Phobos?
- Jonathan M Davis (18/22) Aug 29 2011 It _is_ multi-dimensional. I'm not quite sure why Timon is saying that i...
Take a look: void main() { int[2] single; // foo(single); // no foo(single[]); // int[2][] slice, ok int[2][2] multi; // bar(multi); // int[2][2] no // bar(multi[]); // int[2][] slice, no // bar(multi[][]); // int[2][] slice, no } void foo(int[] value) {} void bar(int[][] value) {} I can easily slice a one-dimensional static array, but I can only slice a single dimension. So how do I pass a multidimensional static array to a function expecting a multidimensional dynamic array?
Aug 29 2011
On 08/30/2011 01:29 AM, Andrej Mitrovic wrote:Take a look: void main() { int[2] single; // foo(single); // no foo(single[]); // int[2][] slice, ok int[2][2] multi; // bar(multi); // int[2][2] no // bar(multi[]); // int[2][] slice, no // bar(multi[][]); // int[2][] slice, no } void foo(int[] value) {} void bar(int[][] value) {} I can easily slice a one-dimensional static array, but I can only slice a single dimension. So how do I pass a multidimensional static array to a function expecting a multidimensional dynamic array?D does not have multidimensional dynamic arrays. To solve your problem, you have to manually create an array of 1D-slices: Like this: bar(array(map!((int[] a){return a;})(multi[]))); Or like this: int[][] arg=new int[][](2); foreach(i,ref x;arg) x=multi[i][]; bar(arg);
Aug 29 2011
Timon Gehr:bar(array(map!((int[] a){return a;})(multi[])));Simpler: bar( array(map!q{ a[] }(multi[])) ); Simpler still when we'll get amap: bar( amap!q{ a[] }(multi[]) ); Bye, bearophile
Aug 29 2011
On 08/30/2011 03:20 AM, bearophile wrote:Timon Gehr:And buggy. It returns slices of a local stack frame, because static arrays are value types.bar(array(map!((int[] a){return a;})(multi[])));Simpler: bar( array(map!q{ a[] }(multi[])) );Simpler still when we'll get amap: bar( amap!q{ a[] }(multi[]) ); Bye, bearophile
Aug 30 2011
Timon Gehr Wrote:On 08/30/2011 03:20 AM, bearophile wrote:q{ a[] } does the same thing as (int[] a){return a;}, both return a slice of memory on the stack. Using a dynamic array (a slice) that uses memory allocated on the stack is correct. You just have to know what you are doing. It's the same as passing a fixed-sized array to a function that expects a dynamic slice. Andrej Mitrovic has said: "I was just trying to temporarily avoid GC allocation so I've used a static array instead of a dynamic ones." If you replace the map function with q{ a.dup } you have heap memory, but Andrej is not happy. Bye, bearophileTimon Gehr:And buggy. It returns slices of a local stack frame, because static arrays are value types.bar(array(map!((int[] a){return a;})(multi[])));Simpler: bar( array(map!q{ a[] }(multi[])) );
Aug 30 2011
On 08/30/2011 01:06 PM, bearophile wrote:Timon Gehr Wrote:No, what they do is very different. Yours creates a new stack frame, copies the data into it and then returns invalid slices to the stack frame that has now disappeared. Mine returns slices to the enclosing stack frame, which is perfectly valid. If you are not convinced, just try to pass a 2D static array to the following function using your method: void bar(int[][] a){writeln(a);} It won't work.On 08/30/2011 03:20 AM, bearophile wrote:q{ a[] } does the same thing as (int[] a){return a;}, both return a slice of memory on the stack. Using a dynamic array (a slice) that uses memory allocated on the stack is correct. You just have to know what you are doing. It's the same as passing a fixed-sized array to a function that expects a dynamic slice.Timon Gehr:And buggy. It returns slices of a local stack frame, because static arrays are value types.bar(array(map!((int[] a){return a;})(multi[])));Simpler: bar( array(map!q{ a[] }(multi[])) );
Aug 30 2011
Timon Gehr:It won't work.Thank you, bye, bearophile
Aug 30 2011
Right, but I was just trying to temporarily avoid GC allocation so I've used a static array instead of a dynamic ones. Also, I don't know of another term that is used to describe a int[][] array, other than multidimensional. Anyway this works fine for me (int wasn't a requirement in this case): void foo(T)(T val) if (isArray!T) void bar(T)(T val) if (isArray!T && isArray!(ElementType!T))
Aug 29 2011
Hey btw, do you think we could use this in Phobos? template BaseElementType(R) { static if (isArray!(ElementType!R)) alias BaseElementType!(ElementType!R) BaseElementType; else static if (is(typeof({return R.init.front();}()) T)) alias T BaseElementType; else alias void BaseElementType; } assert(is(BaseElementType!(int[][]) == int)); Maybe a better name is RootElementType. Not too sure.
Aug 29 2011
On Tuesday, August 30, 2011 03:43:39 Andrej Mitrovic wrote:Right, but I was just trying to temporarily avoid GC allocation so I've used a static array instead of a dynamic ones. Also, I don't know of another term that is used to describe a int[][] array, other than multidimensional.It _is_ multi-dimensional. I'm not quite sure why Timon is saying that it isn't. Ultimately though, a multi-dimensional dynamic array is an array of arrays (or array of arrays of arrays of ...). When slicing it, you get the a portion of the outermost array. If you index that, you can get at the inner arrays to slice those if you want to, but the inner arrays know nothing about the outer arrays, and actually taking a "slice" of the whole where you get the outer array and some portion of the inner arrays would require creating a new array, so you can't really do it. I can't really think of a clean way of explaining it without diagrams, and even then it's a bit of a pain, but with a slice, it's only a matter of adjusting its ptr and length properties. If you want a multi-dimensional slice, you'd need to adjust the ptr and length properties of the arrays that the slice contained, and you can't do that without affecting the original arrays unless you copy them. So, ultimately, you need to construct a new multi-dimensional array with the pieces that you want if you want a multi- dimensional slice. - Jonathan M Davis
Aug 29 2011