I've found a very annoying bug in swift 5.4. Consider the following:
enum Scope {
case ugcImageUpload
case userReadPlaybackState
case userModifyPlaybackState
}
extension Scope: CaseIterable {
static let allCases: Set<Scope> = [ // Invalid redeclaration of synthesized implementation for protocol requirement 'allCases'
.ugcImageUpload,
.userReadPlaybackState,
.userModifyPlaybackState
]
}
print(Scope.allCases) // Error: Ambiguous use of 'allCases'
// presumably because both the synthesized implementation and my implementation exist.
For some reason, I am unable to override the default implementation of allCases for CaseIterable
when the type is Set<Scope>. Interestingly, If I add print(Scope.AllCases.self) and option-click on it, the value of AllCases is [Scope], not Set<Scope>:
At the same time, I do not really think it is wise to change AllCases into a Set, because that may reduce the performance of iteration, which is the intended use for CaseIterable. I am not really sure why you would need a fast membership check when by definition the result would have to be true anyway. But if some external constraints somehow require it, then I would create a protocol of your own instead of (or inheriting from) CaseIterable.
That isn't the only benefit of using a set, and it isn't the reason I'm using it here.
The reason that I'm using a set is because all of the other APIs in my library use Set<Scope>. This
prevent duplicates, which don't make sense for this type, allows order order-insensitive comparisons, and allows for mathematical set operations like isSubset.
Yes. Although exactly how much of a difference depends on what you end up doing with it, and it may very well be negligible for your use case.
Array is designed to optimize retrieval of elements in order, or at a particular offset. But by arranging its guts at even intervals in memory to make that fast, it has no quick way to check for membership. contains(_:) must blindly check each entry until it finds a match or has exhaustively checked everything.
Set is the other way around. It is designed to optimize membership checks. But by arranging its guts in a hash table to make that fast, it has to do a little more work digging in buckets to find the location of the next element of the set.