2

I want to create an Array extension that does this:-

func pairs(tmp: [Any]) -> [(Any, Any)] {
    return Array(Zip2(tmp[0..<tmp.count-1], tmp[1..<tmp.count]))
}

which works fine, but if I wrap it in extension Array:-

extension Array {
    func pairs<T>() -> [(T, T)] {
        return Array(Zip2(self[0..<self.count-1], self[1..<self.count]))
    }
}

The compiler complains:-

Cannot find an initializer for type 'Array<T>' that accepts an argument list of type '(Zip2<Slice<T>, Slice<T>>)'

(also, is the method signature correct? still trying to get my head around the generics syntax)

akbsteam
  • 253
  • 2
  • 16
  • btw, you can write this slightly more succinctly as `func pairs() -> [(T, T)] { return Array<(T, T)>(zip(self, dropFirst(self))) }` – zip will only go as far as the shortest of the two sequences. – Airspeed Velocity Mar 06 '15 at 22:02
  • thanks; always good to see neater ways of doing things – akbsteam Mar 07 '15 at 11:55

1 Answers1

2

This could be a bug (tested with Xcode 6.1.1 and Xcode 6.3 beta 2). It compiles and works in a function, and even in a generic function:

func pairs<T>(tmp: [T]) -> [(T, T)] {
    return Array(Zip2(tmp[0..<tmp.count-1], tmp[1..<tmp.count]))
}

But it does not compile in an Array extension method. As a workaround, you can specify the generic type explicitly in the constructor:

extension Array {
    func pairs() -> [(T, T)] {
        return Array<(T, T)>(Zip2(self[0..<self.count-1], self[1..<self.count]))
    }
}

let a = [1, 2, 3, 4]
let b = a.pairs()
println(b) // [(1, 2), (2, 3), (3, 4)]

Also note that the pairs() method does not specify the placeholder type <T> again, see for example How can I extend typed Arrays in Swift?.

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382