Another way to explain why I'd like to be able to use my type(s) with for-in without getting all stuff from SequenceType et al might be by this example:
TL;DR:
My StaticArrayType(s) has type-level Count, thus SequenceType == bad fit, OK, fine, makes sense. But I'd still like to:
for e in myStaticArray { … }
I could have, if only the stdlib had a simpler protocol whose only requirement was that conforming types had a generate() method.
I have a protocol called StaticArrayType which describes a set of common requirements for concrete (value) types that have/are a statically allocated fixed number of elements (of type Element). So the memory layout of any static array type is fixed and both its element type and its count are encoded at the type level by associated types
Element: DefaultInitializable and
Count: CountType.
The Count type can be used to type check the number of elements and the Element type can be used to type check the element type.
(The memory layout of any static array type is fixed and "known" since eg a static-array-type of 4 Floats (StaticArray<Float>.WithCount4), will have a strideof that is 4 * strideof(Float) == 16 bytes.)
These types are all subscriptable, have count and indices properties etc. Much like a MutableCollectionType. I have working code for this, and it's a very useful zero cost abstraction (the optimizer generates code that is the same as if I had used corresponding simd types, etc). However:
As already mentioned, the StaticArrayType protocol can be made to ineherit from eg MutableCollectionType, but I decided not to, for reasons like these:
- SubSequence doesn't make sense for StaticArrayType (making sense would mean being a different type for each different length/count).
- The same is true for eg map, filter, etc. (They would have to return different types depending on the count of the result).
Put differently: As the count (number of elements) of a StaticArrayType is a type-level thing, it doesn't make sense to mix it with constructs in which the count is a runtime thing (such as CollectionType, SubSequence and SequenceType).
So it ends up being better to redefine any possibly relevant similar concepts (eg SubSequence, MutableSlice, map, filter etc) specifically for StaticArrayType.
Note that I am totally fine with not having my StaticArrayType protocol inherit from CollectionType/SequenceType, as it makes perfect sense (for the reasons outlined above).
BUT this also has one (somewhat surprising) consequence, namely that I will not be able to write this:
1. for e in myStaticArray { ... use e in some (non-mutating) way ... }
but instead I have to write this:
2. for i in myStaticArray.indices { ... use myStaticArray[i] in some (non-mutating) way ... }
So why shouldn't my StaticArrayType be able to inherit from some less bloated / presumptuous protocol that simply had _one_ requirement:
That the type has a generate method and thus can be used in a for-in statement like (1) above.
?
Or: Why does for-in statements like (1) require SequenceType conformance when the only thing they actually need is a generate() method?