Comment #0 by bearophile_hugs — 2011-02-21T15:55:16Z
A D2 demo program:
import std.range, std.stdio;
void main() {
auto c1 = chain([1, 2], [3, 4]);
writeln(c1);
writeln(typeid(typeof(c1)));
auto c2 = chain(c1, [5, 6]);
writeln(c2);
writeln(typeid(typeof(c2)));
auto c3 = chain([1, 2], [3, 4], [5, 6]);
writeln(c3);
writeln(typeid(typeof(c3)));
}
It prints, with DMD 2.052:
[1, 2, 3, 4]
std.range.ChainImpl!(int[],int[]).ChainImpl
[1, 2, 3, 4, 5, 6]
std.range.ChainImpl!(ChainImpl!(int[],int[]),int[]).ChainImpl
[1, 2, 3, 4, 5, 6]
std.range.ChainImpl!(int[],int[],int[]).ChainImpl
I suggest to add some simple automatic simplifications to chain(), so c2 has the same type of c3:
chain(chain(something), r2) ==> chain(something, r2)
chain(r1, chain(something)) ==> chain(r1, something)
chain(chain(something1), chain(something2)) ==> chain(something1, something2)
To perform them chain() just needs to recognize the type of itself among its iterable arguments and return a chain of the arguments of the sub-chains.
This flattening is useful to speed up the code with complex nested/paired chainings, like ones coming from recursive algorithms.
Comment #1 by lt.infiltrator — 2014-03-19T16:14:10Z
For the examples you provided, v2.065 gives the same typeid for all of them:
--------------------------------------------------------------------
import std.range, std.stdio;
void main() {
auto c1 = chain(chain([1, 2]), [3, 4]);
writeln(c1);
writefln("chain(chain, range): %s", typeid(typeof(c1)));
auto c2 = chain([1, 2], chain([3, 4]));
writeln(c2);
writefln("chain(range, chain): %s", typeid(typeof(c2)));
auto c3 = chain(chain([1, 2]), chain([3, 4]));
writeln(c3);
writefln("chain(chain, chain): %s", typeid(typeof(c3)));
}
--------------------------------------------------------------------
Application output:
[1, 2, 3, 4]
chain(chain, range): std.range.chain!(int[], int[]).chain.Result
[1, 2, 3, 4]
chain(range, chain): std.range.chain!(int[], int[]).chain.Result
[1, 2, 3, 4]
chain(chain, chain): std.range.chain!(int[], int[]).chain.Result