Swift operators on arrays whose contents match specific protocols, "where" keyword usage

Viewed 65

I'm trying to make a Swift operator that applies to all Arrays which contain only Numeric elements, it should look something like this:

prefix operator ∑
prefix func ∑ (array: Array<T>) -> T where T == Numeric {
    var sum: T = 0
    for item in array {
        sum += item
    }
    return sum
}

but that's a compiler error (error: 'where' clause cannot be attached to a non-generic declaration)

I could, of course, write many functions in the form:

prefix operator ∑
prefix func ∑ (array: Array<Double>) -> Double {
    var sum: Double = 0
    for item in array {
        sum += item
    }
    return sum
}

which works, but the point of generics is that I shouldn't have to.

This is probably because I don't understand how to use the "where" keyword, but I'm finding it difficult to search for such a (no pun intended) generic word, as I get too many irrelevant results.

Edit:

And I can't write prefix func ∑ (array: Array<Numeric>) -> Numeric { because then Swift can't figure out how to compile sum += item.

2 Answers

You could constraint the generic type to be a Numeric by typing <T: Numeric>, thus the signature of the function would be:

func ∑ <T: Numeric>(array: Array<T>) -> T

I would also suggest to use reduce(_:_:) method to achieve such a task:

prefix operator ∑
prefix func ∑ <T: Numeric>(array: Array<T>) -> T {
    return array.reduce(0, +)
}

// calling:
let array = Array(repeating: 1, count: 20)
let summation = ∑array // 20

For more information about generics type constraints, you could review official documentation.

prefix operator ∑
prefix func ∑ <T>(array: Array<T>) -> T where T: Numeric {
    var sum: T = 0
    for item in array {
        sum += item
    }
    return sum
}
Related