`Algorithms`

package `product(_:_:)`

supports product of a `Sequence`

and a `Collection`

, allow for heterogeneous element types. To do product of more than two terms, you have to call nested `product(_:_:)`

and the result is in tuple, resulting in static code of fixed n-number of terms must be known in compile time.. This is fine when product terms element types are heterogeneous.

But for homogeneous element type for all product terms, there should be `product(...)`

that can calculate product of any number of terms, allowing for dynamically handle any number of product terms.

This is what I come up with:

```
@inlinable
public func product<C: Collection>(_ terms: Array<C>) -> Array<Array<C.Element>> {
switch terms.count {
case 0:
return []
case 1:
return terms[0].map { [$0] }
default:
var result = product(terms[0], terms[1]).map { [$0, $1] }
for term in terms.dropFirst(2) {
result = product(result, term).map { $0.0 + [$0.1] }
}
return result
}
}
// Special case for Character:
public func product<C: Collection>(_ terms: Array<C>) -> [String] where C.Element == Character {
switch terms.count {
case 0:
return []
case 1:
return terms[0].map { String($0) }
default:
var result = product(terms[0], terms[1]).map { String([$0, $1]) }
for term in terms.dropFirst(2) {
result = product(result, term).map { $0.0 + String($0.1) }
}
return result
}
}
```

With this, we can do this:

```
let blah = product([[1,2,3], [4,5,6,7], [8,9,0]])
print(blah)
```

prints:

```
[[1, 4, 8], [1, 4, 9], [1, 4, 0], [1, 5, 8], [1, 5, 9], [1, 5, 0], [1, 6, 8], [1, 6, 9], [1, 6, 0], [1, 7, 8], [1, 7, 9], [1, 7, 0], [2, 4, 8], [2, 4, 9], [2, 4, 0], [2, 5, 8], [2, 5, 9], [2, 5, 0], [2, 6, 8], [2, 6, 9], [2, 6, 0], [2, 7, 8], [2, 7, 9], [2, 7, 0], [3, 4, 8], [3, 4, 9], [3, 4, 0], [3, 5, 8], [3, 5, 9], [3, 5, 0], [3, 6, 8], [3, 6, 9], [3, 6, 0], [3, 7, 8], [3, 7, 9], [3, 7, 0]]
```

I've not look in other algorithms if they are in similar situation.