Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Error: 'Sequence' requires the types 'T' and 'ArraySlice<T>' be equivalent

Tags:

swift

swift4

I'm trying to update a math library to be compatible with Swift 3, but I'm running into an error:

'Sequence' requires the types 'T' and 'ArraySlice<T>' be equivalent

Apple's documentation on Sequence recommends that makeIterator() method returns an iterator, which it does. And it seems that the iterator is returning an element in the grid variable, which is of variable T. I'm not quite sure what I'm missing here. Any advice would be helpful.

public struct Matrix<T> where T: FloatingPoint, T: ExpressibleByFloatLiteral {
    public typealias Element = T

    let rows: Int
    let columns: Int
    var grid: [Element]

    public init(rows: Int, columns: Int, repeatedValue: Element) {
        self.rows = rows
        self.columns = columns

        self.grid = [Element](repeating: repeatedValue, count: rows * columns)
    }
... 
}

extension Matrix: Sequence { // <-- getting error here
    public func makeIterator() -> AnyIterator<ArraySlice<Element>> {
        let endIndex = rows * columns
        var nextRowStartIndex = 0

        return AnyIterator {
            if nextRowStartIndex == endIndex {
                return nil
            }

            let currentRowStartIndex = nextRowStartIndex
            nextRowStartIndex += self.columns

            return self.grid[currentRowStartIndex..<nextRowStartIndex]
        }
    }
}
like image 993
dmr07 Avatar asked Aug 14 '17 06:08

dmr07


1 Answers

Your code compiles fine as Swift 3.1 (Xcode 8.3.3). The error

'Sequence' requires the types 'T' and 'ArraySlice<T>' be equivalent

occurs when compiling as Swift 4 (Xcode 9, currently beta), because then the Sequence protocol already defines the

associatedtype Element where Self.Element == Self.Iterator.Element

which conflicts with your definition. You can either choose a different name for your type alias, or just remove it (and use T instead):

public struct Matrix<T> where T: FloatingPoint, T: ExpressibleByFloatLiteral {

    let rows: Int
    let columns: Int
    var grid: [T]

    public init(rows: Int, columns: Int, repeatedValue: T) {
        self.rows = rows
        self.columns = columns

        self.grid = [T](repeating: repeatedValue, count: rows * columns)
    }
}

extension Matrix: Sequence {
    public func makeIterator() -> AnyIterator<ArraySlice<T>> {
        let endIndex = rows * columns
        var nextRowStartIndex = 0

        return AnyIterator {
            if nextRowStartIndex == endIndex {
                return nil
            }

            let currentRowStartIndex = nextRowStartIndex
            nextRowStartIndex += self.columns

            return self.grid[currentRowStartIndex..<nextRowStartIndex]
        }
    }
}

This compiles and runs with both Swift 3 and 4.

like image 173
Martin R Avatar answered Oct 15 '22 05:10

Martin R