Thread overview
Fixed matrix rows joining
Jan 15, 2012
bearophile
Jan 15, 2012
Andrej Mitrovic
Jan 15, 2012
Andrej Mitrovic
Jan 15, 2012
Peter Alexander
Jan 15, 2012
Timon Gehr
January 15, 2012
If I have a simple fixed-size matrix and I need to linearize (flatten) it, the function join() seems to not not work:


import std.array: join;
void main() {
    int[4][4] table;
    join(table);
}


test.d(4): Error: template std.array.join(RoR,R) if (isInputRange!(RoR) && isInputRange!(ElementType!(RoR)) && isForwardRange!(R) && is(Unqual!(ElementType!(ElementType!(RoR))) == Unqual!(ElementType!(R)))) does not match any function template declaration
test.d(4): Error: template std.array.join(RoR,R) if (isInputRange!(RoR) && isInputRange!(ElementType!(RoR)) && isForwardRange!(R) && is(Unqual!(ElementType!(ElementType!(RoR))) == Unqual!(ElementType!(R)))) cannot deduce template function from argument types !()(int[4u][4u])


This too doesn't work:
join(table[]);



This compiles:
join(map!q{ a[] }(table[]));


But this program shows there is something wrong (I know what's wrong), it prints: [6, 4219787, 4, 6, 4219787, 4]


import std.stdio: writeln;
import std.algorithm: map;
import std.array: join;
void main() {
    int[3][2] table = [[1,2,3],[4,5,6]];
    int[] result = join(map!q{ a[] }(table[]));
    writeln(result);
}



This prints the right output, but it allocates lot of memory: [1, 2, 3, 4, 5, 6]


import std.stdio: writeln;
import std.algorithm: map;
import std.array: join;
void main() {
    int[3][2] table = [[1,2,3],[4,5,6]];
    int[] result2 = join(map!q{ a.dup }(table[]));
    writeln(result2);
}


Do you have better suggestions?
Is the function join() worth fixing/changing to improve this use case?

Bye,
bearophile
January 15, 2012
A rectangular array is really just one array, is it not? From a syntax point it looks like a multidimensional array but really it's just a single linear piece of memory, so just cast it:

void main()
{
    int[2][4] table;
    table[0][] = 0;
    table[1][] = 1;
    table[2][] = 2;
    table[3][] = 3;
    auto x = cast(int[])table;
    assert(x == [0, 0, 1, 1, 2, 2, 3, 3]);
}
January 15, 2012
I guess join() could be specialized for static arrays and then just do a dup and a cast? Would that work ok?
January 15, 2012
On 15/01/12 2:19 AM, Andrej Mitrovic wrote:
> I guess join() could be specialized for static arrays and then just do
> a dup and a cast? Would that work ok?

There should be no need to allocate extra memory to do this.
January 15, 2012
On 01/15/2012 02:38 AM, bearophile wrote:
> If I have a simple fixed-size matrix and I need to linearize (flatten) it, the function join() seems to not not work:
>
>
> import std.array: join;
> void main() {
>      int[4][4] table;
>      join(table);
> }
>
>
> test.d(4): Error: template std.array.join(RoR,R) if (isInputRange!(RoR)&&  isInputRange!(ElementType!(RoR))&&  isForwardRange!(R)&&  is(Unqual!(ElementType!(ElementType!(RoR))) == Unqual!(ElementType!(R)))) does not match any function template declaration
> test.d(4): Error: template std.array.join(RoR,R) if (isInputRange!(RoR)&&  isInputRange!(ElementType!(RoR))&&  isForwardRange!(R)&&  is(Unqual!(ElementType!(ElementType!(RoR))) == Unqual!(ElementType!(R)))) cannot deduce template function from argument types !()(int[4u][4u])
>
>
> This too doesn't work:
> join(table[]);
>
>
>
> This compiles:
> join(map!q{ a[] }(table[]));
>
>
> But this program shows there is something wrong (I know what's wrong), it prints:
> [6, 4219787, 4, 6, 4219787, 4]
>
>
> import std.stdio: writeln;
> import std.algorithm: map;
> import std.array: join;
> void main() {
>      int[3][2] table = [[1,2,3],[4,5,6]];
>      int[] result = join(map!q{ a[] }(table[]));
>      writeln(result);
> }
>
>
>
> This prints the right output, but it allocates lot of memory:
> [1, 2, 3, 4, 5, 6]
>
>
> import std.stdio: writeln;
> import std.algorithm: map;
> import std.array: join;
> void main() {
>      int[3][2] table = [[1,2,3],[4,5,6]];
>      int[] result2 = join(map!q{ a.dup }(table[]));
>      writeln(result2);
> }
>
>
> Do you have better suggestions?

join(map!((int[] a)=>a)(table[]))

although I'd like

join(map!((ref a)=>a[])(table[]))

to work. I'll file an enhancement.

> Is the function join() worth fixing/changing to improve this use case?
>
> Bye,
> bearophile