Looks like you can't. The closest we can get is the function
func sum(a:Array<Int>) -> Int {
return a.reduce(0) {$0 + $1}
}
Swift will allow you to add extension on the Array class but not specifically to a specialized version of the class.
error: <REPL>:108:1: error: non-nominal type 'Array<Int>' cannot be extended
You can extend the Array class.
extension Array {
func sum() -> Int {
return reduce(0) { $0 + $1 }
}
}
The problem is now with the +
operator
error: <REPL>:102:16: error: could not find an overload for '+' that accepts the supplied arguments
return reduce(0) { $0 + $1 }
This is somewhat expected since we cannot be sure that the +
operator will be will be overloaded for all the possible types that could be used in an array.
So we could try to constraint the operation only on certain classes. Something like
class Dummy {
}
extension Array {
func someFunc<T:Dummy>() -> Int {
return 0
}
}
var l = [Dummy()]
var r = l.someFunc() // Expect 0
Conceptually this should work (currently it seems that there is a bug, Xcode crashes when evaluating a playground using this code). In the eventually that it works, we cannot use this trick since the type Int
is not a class.
extension Array {
func sum<T:Int>() -> T {
return reduce(0) { $0 + $1 }
}
}
error: <REPL>:101:14: error: inheritance from non-protocol, non-class type 'Int'
func sum<T:Int>() -> T {
I also looked at extending the Array class with a protocol but again Int
not being a class makes it impossible. If the numeric types were classes, it would be nice if we could have a protocol to define that a class can be added just like Comparable
or Equatable
but my understanding is that protocol cannot define generic function which would be needed to create a Addable
protocol.
Edit:
As stated by other answers, you can make it work for Int by explicitly checking and casting to Int in the closure. I guess I missed it will investigating. But it would still be nice if we could have a generic way of working with numeric types.