Extend array types using where clause in Swift
Swift 3 on Xcode 8.2
Just need to extend Sequence protocol and provide a where statement.
let someString = "1, 2, 3, 4, 5, 6, 7, 8"
extension String {
func toArrayOfElements() -> [String] {
return self.components(separatedBy: ", ")
}
}
extension Sequence where Iterator.Element == String {
func toInt() -> [Int] {
return self.map {
Int($0)!
}
}
}
let arrayOfStrings = someString.toArrayOfElements()
print(arrayOfStrings)
let arrayOfInts = arrayOfStrings.toInt()
print(arrayOfInts)
Swift 3 to the rescue!!
extension Collection where Iterator.Element == Int {
// `Collection` can be `Sequence`, etc
}
How about
extension CollectionType where Generator.Element == Double {
}
Or If you want a little bit more:
protocol ArithmeticType {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
}
extension Double : ArithmeticType {}
extension Float : ArithmeticType {}
extension SequenceType where Generator.Element : protocol<FloatLiteralConvertible, ArithmeticType> {
var sum : Generator.Element {
return reduce(0.0, combine: +)
}
var product : Generator.Element {
return reduce(1.0, combine: *)
}
}
stride(from: 1.0, through: 10.0, by: 1.0).sum // 55
[1.5, 2.0, 3.5, 4.0, 5.5].product // 231
Works with Double
and Float
or any other type that you conform to the protocols ArithmeticType
and FloatLiteralConvertible
. If you need to access specific indices of your array, change SequenceType
to CollectionType
as you cannot do this with a sequence.
If you want to extend only array with specific type. You should extend _ArrayType protocol.
extension _ArrayType where Generator.Element == Int {
func doSomething() {
...
}
}
If you extend Array
you can only make sure your element is conformed some protocol else. i.e:
extension Array where Element: Equatable {
func doSomething() {
...
}
}
Updated: With Swift 3.1 https://github.com/apple/swift/blob/master/CHANGELOG.md
extension Array where Element == Int {
func doSomething() {
...
}
}