Swift позволяет создать расширение массива, которое суммирует Integer с:
extension Array {
func sum() -> Int {
return self.map { $0 as Int }.reduce(0) { $0 + $1 }
}
}
Что теперь можно использовать для суммирования Int[]
как:
[1,2,3].sum() //6
Но как мы можем создать общую версию, которая поддерживает суммирование других типов Number, таких как Double[]
?
[1.1,2.1,3.1].sum() //fails
Этот вопрос НЕ как суммировать числа, но как создать универсальное расширение массива, чтобы сделать это.
Ускорение
Это самый близкий, который мне удалось получить, если он поможет кому-то приблизиться к решению:
Вы можете создать протокол, который может выполнять то, что нам нужно сделать, например:
protocol Addable {
func +(lhs: Self, rhs: Self) -> Self
init()
}
Затем продолжите каждый из типов, которые мы хотим поддерживать, которые соответствуют указанному выше протоколу:
extension Int : Addable {
}
extension Double : Addable {
}
Затем добавьте расширение с этим ограничением:
extension Array {
func sum<T : Addable>(min:T) -> T
{
return self.map { $0 as T }.reduce(min) { $0 + $1 }
}
}
Что теперь можно использовать против числа, которое мы расширили для поддержки протокола, т.е.
[1,2,3].sum(0) //6
[1.1,2.1,3.1].sum(0.0) //6.3
К сожалению, я не смог заставить его работать, не предоставляя аргумент, т.е.
func sum<T : Addable>(x:T...) -> T?
{
return self.map { $0 as T }.reduce(T()) { $0 + $1 }
}
Измененный метод все еще работает с одним аргументом:
[1,2,3].sum(0) //6
Но не удается разрешить метод при вызове без аргументов, т.е.
[1,2,3].sum() //Could not find member 'sum'
Добавление Integer
к сигнатуре метода также не помогает решению метода:
func sum<T where T : Integer, T: Addable>() -> T?
{
return self.map { $0 as T }.reduce(T()) { $0 + $1 }
}
Но, надеюсь, это поможет другим приблизиться к решению.
Некоторый прогресс
Из ответа @GabrielePetronella, похоже, мы можем вызвать вышеупомянутый метод, если мы явно укажем тип на сайте-вызове, например:
let i:Int = [1,2,3].sum()
let d:Double = [1.1,2.2,3.3].sum()