[swift-evolution] Compile-time generic specialization
Abe Schneider
abe.schneider at gmail.com
Fri Feb 10 12:08:10 CST 2017
>
> Other languages in the C family (e.g., C#, Java) that have both generics and ad hoc overloading provide the same static-resolution behavior that Swift does, so someone coming from a language in the general “C” family will be confounded whatever we choose. Personally, I think C++ got this wrong—I feel that generic algorithm customization points and algorithm specializations should be explicitly stated, because it makes it easier to reason about the generic code if you know where those points are. Swift uses protocol requirements for customization points, but hasn’t tackled algorithm specialization yet.
That's a fair point, though I think Java's type erasure in generics
surprises/confuses a lot of people (and takes away a lot of the
potential power of generics). That's not to say C++ templates are easy
to understand (e.g. SFINAE), but at least to me it operates in a more
intuitive manner until you get to the esoteric parts. And that is
admittedly a very subjective point.
I can see the advantage of protocols if they allowed this type of design:
protocol LinearOperations {
associatedtype StorageType
static func dot(_ lhs:Tensor<StorageType>, _
rhs:Tensor<StorageType>) -> Tensor<StorageType>
...
}
extension Tensor: LinearOperations {
...
}
extension Tensor: LinearOperations where StorageType:CBlasStorage<Float> {
...
}
The advantage of this design is that the available functions are
clearly defined, but it still allows new operations to be defined
without having to touch the main code base. You can also easily add
new functionality to the Tensor class by creating a new protocol:
protocol StatisticsOperations {
associatedtype StorageType
static func histogram(_ tensor:Tensor<StorageType>) -> Tensor<StorageType>
}
extension Tensor: StatisticsOperations {
...
}
The two disadvantages are: (a) Swift currently doesn't allow this; and
(b) it's a little more verbose because you have to write:
let result = Tensor.histogram(mydata)
versus:
let result = histogram(mydata)
which has the redundant piece of information that it's a Tensor (which
can be inferred from `mydata`).
Abe
More information about the swift-evolution
mailing list