transposed unnecessarily complicated, fundamentally wrong, overly opinionated
unittest{
int[][] foo=[[1,2,3],[4,5,6],[7,8,9]];
foo.transposed.writeln;
foo.writeln; //prints []
}
By trying to avoid one allocation, transposed picks up unnecessary constraints and violates "view of data".
Instead it should just eagerly call the .array on the range of ranges for me as thats usually more correct and the only way it compiles anyway.
Instead it should just eagerly call the .array on the range of ranges for me
That's potentially a breaking change for @nogc code. What's the advantage of that vs just using transposed(foo.array)?
Im unaware of a single range it would handle correctly, Im always rediscovering that .array is nessery glue code
import std;
auto transposed(R)(R r)=>std.range.transposed(r.array);//toggle this line
int i=1;
void sanitychecks(R)(R r){
writeln("test ",i++);
static if( ! __traits(compiles,r.transposed)){
"doesnt even compile".writeln;
} else {
assert( ! r.front.empty,"please pass non empty ranges test");
r.transposed.writeln;
zip(r.joiner,r.transposed.joiner).writeln;
if(r.front.empty){ ":O but we checked that wasnt true".writeln;}
}}
unittest{
sanitychecks([[1,2,3],[4,5,6],[7,8,9]]);
auto arange=[iota(0,3),iota(3,6),iota(6,9)];
sanitychecks(arange);
sanitychecks(arange.map!(a=>a.map!(a=>a+1)));
sanitychecks(arange.map!(a=>a.map!(b=>a.front+b)));
}
struct Transposed(RangeOfRanges,
TransverseOptions opt = TransverseOptions.assumeJagged)
if (isForwardRange!RangeOfRanges &&
isInputRange!(ElementType!RangeOfRanges) &&
hasAssignableElements!RangeOfRanges)
{
all this header is about pushing this allocation to the user
Related: #10766
it is a bug were a trivial fix would be to alway allocate