Derleme zamanında örneğin int, string, double elemanlı 3 dizi varsa sonucun Tuple!(int, string, double) olduğu bilinebiliyor ve kod o biçimde derleniyor. Ama dizi (tabii, daha doğru olara herhangi bir aralık türü) sayısı baştan bilinmeyince sonucun türü de bilinemiyor.
Bütün dizilerin eleman türleri aynı olduğunda cartesianProduct'ın türünü bir dizi olarak gösterebiliriz. Örneğin, int elemanlı üç dizi çarpıldığında her eleman 3 uzunluklu int[] olabilir:
import std.stdio;
import std.algorithm;
import std.range;
auto cartesianProductDynamic(R)(R[] aralıklar) {
assert(!aralıklar.empty);
switch (aralıklar.length) {
case 1:
// Tek dizinin cartesianProduct'ı kendisidir
return aralıklar;
break;
case 2:
// Phobos'unkini çağırıyoruz ama elemanları Tuple'dan dilime dönüştürüyoruz
return cartesianProduct(aralıklar[0], aralıklar[1]).map!(t => t.array).array;
break;
default:
// Yine Phobos'unkini çağırıyoruz ama elemanları Tuple'dan dilime dönüştürüyoruz
return cartesianProduct(aralıklar[0], cartesianProductDynamic(aralıklar[1..$]))
.map!(t => t[0] ~ t[1]).array;
break;
}
}
void main() {
auto a = [ 1, 2 ];
auto b = [ 33, 44 ];
auto c = [ 555, 666, 777 ];
// Kaç adet oldukları derleme zamanında bilinmeyen aralıklar. (Tabii bu durumda 3 ama olsun.)
auto aralıklar = [ a, b, c ];
auto sonuç = cartesianProductDynamic(aralıklar);
writefln("%(%s\n%)", sonuç);
}
'
[1, 33, 555]
[1, 33, 666]
[1, 33, 777]
[1, 44, 555]
[1, 44, 666]
[1, 44, 777]
[2, 33, 555]
[2, 33, 666]
[2, 33, 777]
[2, 44, 555]
[2, 44, 666]
[2, 44, 777]
'
Derlenebilmesi için bir sürü .array kullanmak zorunda kaldım; performans sorunu oluşturabilirler.
Elemanlar aynı olmadıklarında Variant'tan yararlanmak gerekecektir. O zaman sonucun her elemanı bir Variant dizisi olur.
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]