@@ -11226,9 +11226,10 @@ unittest
1122611226
1122711227// cartesianProduct
1122811228/**
11229- Lazily computes the Cartesian product of two ranges $(D range1) and $(D
11230- range2). The product is a _range of tuples of elements from each respective
11231- range.
11229+ Lazily computes the Cartesian product of two or more ranges. The product is a
11230+ _range of tuples of elements from each respective range.
11231+
11232+ The conditions for the two-range case are as follows:
1123211233
1123311234If both ranges are finite, then one must be (at least) a forward range and the
1123411235other an input range.
@@ -11238,6 +11239,9 @@ be a forward _range, and the infinite range can be an input _range.
1123811239
1123911240If both ranges are infinite, then both must be forward ranges.
1124011241
11242+ When there are more than two ranges, the above conditions apply to each
11243+ adjacent pair of ranges.
11244+
1124111245Examples:
1124211246---
1124311247auto N = sequence!"n"(0); // the range of natural numbers
@@ -11465,3 +11469,18 @@ unittest
1146511469 assert (canFind(BC , tuple(n[0 ], n[1 ])));
1146611470 }
1146711471}
11472+
11473+ // / ditto
11474+ auto cartesianProduct (R1 , R2 , RR ... )(R1 range1, R2 range2, RR otherRanges)
11475+ {
11476+ /* We implement the n-ary cartesian product by recursively invoking the
11477+ * binary cartesian product. To make the resulting range nicer, we denest
11478+ * one level of tuples so that a ternary cartesian product, for example,
11479+ * returns 3-element tuples instead of nested 2-element tuples.
11480+ */
11481+ enum string denest = format(" tuple(a[0], %(a[1][%d]%|,%))" ,
11482+ iota(0 , others.length+ 1 ));
11483+ return map! denest(
11484+ cartesianProduct(range1, cartesianProduct (range2, otherRanges))
11485+ );
11486+ }
0 commit comments