I want a way to generate all possible combinations of values when given a list of types that conform to CaseIterable
for a testing harness. I'm at a point where I've gotten stuck, and I'm not quite sure how to reason about the problem at this level of abstraction.
Example
enum CompassDirection: CaseIterable {
case north, south, east, west
}
enum MyEnum: CaseIterable {
case foo, bar, baz
}
enum WorkoutType: CaseIterable {
case cardio
case hiit
case strength
}
let combo = combination(CompassDirection.self, WorkoutType.self, MyEnum.self)
// [(.north, .cardio, .foo), (.north, .cardio, .bar), (.north, .cardio, .baz), ...]
Non-parameter pack 2 case scenario.
This is pretty straightforward, and easy enough to understand, but doesn't support arbitrary numbers of types.
func combination<A: CaseIterable, B: CaseIterable>(_ type1: A, type2: B) -> [(A, B)] {
var result: [(A, B)] = []
for a in A.allCases {
for b in B.allCases {
result.append((a, b))
}
}
return result
}
Attempt with parameter packs
I thought this might be the syntax I wanted, but it doesn't seem to work in two places.
- I can't iterate generically over the tuple elements.
- "<type> cannot conform to <protocol>".
func comb<each T: CaseIterable>(
_ a: repeat (each T).Type
) -> [(repeat each T)] {
var result: [(repeat each T)] = []
let allAllCases = (repeat (each T).allCases) // You now have a tuple of lists...
// ... how do I iterate over the tuple elements here?
return result
}
let combo = comb(CompassDirection.self, WorkoutType.self) // Type 'CompassDirection.Type' cannot conform to 'CaseIterable'
Is this possible in Swift? How? Or, why not?