before we go down the “generic value parameters” path, we need to think about how this is going to fit in with conditional conformances, because that is going to be crucial for the actual usability of this feature. for example, let’s say we want to compute cross products for 2- and 3-dimensional vectors, and we want to factor that into a protocol CrossProductable:
protocol CrossProductable
{
associatedtype CrossProduct
static func >|< (lhs:Self, rhs:Self) -> CrossProduct
}
Currently, the closest thing we have to generic parameterization on element count is using a generic type parameter constrained to conform to SIMD:
struct Vector<Storage, T>
where Storage:SIMD, T:SIMDScalar, T == Storage.Scalar
{
}
typealias Vector2<T> = Vector<SIMD2<T>, T> where T:SIMDScalar
typealias Vector3<T> = Vector<SIMD3<T>, T> where T:SIMDScalar
typealias Vector4<T> = Vector<SIMD4<T>, T> where T:SIMDScalar
typealias Vector8<T> = Vector<SIMD8<T>, T> where T:SIMDScalar
...
a generic type can only have one conditional conformance per protocol, so the following does not work:
// cannot have more than one conditional conformance,
// even with different conditional bounds!
extension Vector:CrossProductable where Storage == SIMD2<T>
{
static func >|< (lhs:Self, rhs:Self) -> T
}
extension Vector:CrossProductable where Storage == SIMD3<T>
{
static func >|< (lhs:Self, rhs:Self) -> Self
}
The workaround is to use a unification protocol on the Storage type, and then write the conditional conformance in terms of the unification protocol:
protocol CrossProductableStorage:SIMD
{
associatedtype CrossProduct
static func cross(a:Self, b:Self) -> CrossProduct
}
extension SIMD2:CrossProductableStorage
{
...
}
extension SIMD3:CrossProductableStorage
{
...
}
extension Vector:CrossProductable
where Storage:CrossProductableStorage
{
static func >|< (lhs:Self, rhs:Self) -> Storage.CrossProduct
}
but it’s hard to see how this could possibly work with value parameters, since values are not types, and cannot be extended.
extension 2 as Int:CrossProductableArity
{
typealias CrossProduct = Int
}
extension 3 as Int:CrossProductableArity
{
// what goes here?? ----------v
typealias CrossProduct = Vector<???, count: 3>
}