Reputation: 59994
As an exercise, I'm trying to extend Array
in Swift to add a sum()
member function. This should be type safe in a way that I want a call to sum()
to compile only if the array holds elements that can be added up.
I tried a few variants of something like this:
extension Array {
func sum<U : _IntegerArithmeticType where U == T>() -> Int {
var acc = 0
for elem in self {
acc += elem as Int
}
return acc
}
}
The idea was to say, “OK, this is a generic function, the generic type must be something like an Int
, and must also be the same as T
, the type of the elements of the array”. But the compiler complains: “Same-type requirement make generic parameters U and T equivalent”. That's right, and they should be, with the additional contraint T : _IntegerArithmeticType
.
Why isn't the compiler letting me do this? How can I do it?
(I know that I should later fix how things are added up and what the return type exactly is, but I'm stuck at the type constraint for now.)
Upvotes: 2
Views: 711
Reputation: 59994
As per Martin R's comment, this is not currently possible. The thing I'm tempted to use in this particular situation would be an explicit passing of a T -> Int
conversion function:
extension Array {
func sum(toInt: T -> Int?) -> Int {
var acc = 0
for elem in self {
if let i = toInt(elem) {
acc += i
}
}
return acc
}
}
Then I can write stuff like this:
func itself<T>(t: T) -> T {
return t
}
let ss = ["1", "2", "3", "4", "five"].sum { $0.toInt() }
let si = [1, 2, 3, 4].sum(itself)
An explicit function has to be passed, though. The (itself)
part can of course be replaced by { $0 }
. (Others have called the itself
function identity
.)
Note that an A -> B
function can be passed when A -> B?
is needed.
Upvotes: 3