Skip to content

Instantly share code, notes, and snippets.

@phlippieb
Created July 7, 2022 05:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phlippieb/54e1ab490dd52ca76c164f4acb4e560b to your computer and use it in GitHub Desktop.
Save phlippieb/54e1ab490dd52ca76c164f4acb4e560b to your computer and use it in GitHub Desktop.
Leveraging Swift's type system to represent the concept of an index type with a fixed size
/**
Leveraging Swift's type system to represent the concept of an index type with a fixed size,
so that iterating over all indices doesn't require a default case.
*/
/// The abstract properties of a fixed-size index type
protocol ExactNumberOfIndices: CaseIterable, RawRepresentable where RawValue == Int {}
/// A concrete fixed-size index type with 1 element (namely 0)
enum _1: Int, ExactNumberOfIndices {
case _0 = 0
}
/// A concrete fixed-size index type with 2 elements (namely 0 and 1)
enum _2: Int, ExactNumberOfIndices {
case _0 = 0, _1
}
enum _3: Int, ExactNumberOfIndices {
case _0 = 0, _1, _2
}
// etc
/**
This allows us to pass an "expected number of items" around as a type.
If we need to iterate over indices, this cleans up the handler.
*/
/// Example function that receives a fixed-size index type as a parameter
func verifyItems<ItemType, IndexType: ExactNumberOfIndices>(
_ items: [ItemType],
hasCount: IndexType.Type,
_ verify: (IndexType, ItemType) -> Void
) {
// Verify that the item count is correct
assert(items.count == IndexType.allCases.count)
// Iterate over each item and verify
zip(IndexType.allCases, items).forEach(verify)
}
/// Example usage
verifyItems([1, 2], hasCount: _2.self) { index, item in
switch index {
case ._0: assert(item == 1)
case ._1: assert(item == 2)
// NOTE: No default case required!
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment