Как вернуть последовательность в Swift?

Я пытаюсь написать расширение для Matrix примера из книги, слегка изменено, чтобы быть общим.
Я пытаюсь написать метод под названием getRow, который возвращает последовательность значений в данной строке.

В С# я бы написал следующее:

IEnumerable<T> GetRow (int row)
{
    return Enumerable
        .Range (0, this.columns)
        .Select ((column) => this.grid[row, columns]);
}

или, альтернативно,

IEnumerable<T> GetRow (int row)
{
    for (var column = 0; column < this.columns; column++) {
        yield return this.grid[row, column];
    }
}

Я не уверен, как это сделать в Swift, хотя.

Sequence кажется эквивалентным IEnumerable<T>, но я не понимаю, почему он использует typealias вместо того, чтобы просто определяться как Sequence<T> (см. также это). Определение метода, возвращающего общий Sequence<T>, не работает:

extension Matrix {
    // Cannot specialize non-generic type 'Sequence'
    func getRow<T>(index: Int) -> Sequence<T> {
        return map(0..self.columns, { self[index, $0] })
    }
}

Затем я избавился от <T> (но как он должен быть общим?):

extension Matrix {
    func getRow(index: Int) -> Sequence {
        return map(0..self.columns, { self[index, $0] })
    }
}

Это компилируется! Однако я не могу его использовать:

var row = grid.getRow(0)
// 'Sequence' does not conform to protocol '_Sequence_'
for i in row {
    println("\(i)")
}

Как правильно напечатать результат map, чтобы его можно было использовать в цикле for..in?

Подробнее об этой проблеме: Связанный тип считается странным

Ответ 1

Joe Groff предложил обернуть результат в SequenceOf<T>:

extension Matrix {
    func getRow(index: Int) -> SequenceOf<T> {
        return SequenceOf(map(0..self.columns, { self[index, $0] }))
    }
}

В самом деле, это работает, но нам пришлось обернуть результат map в класс-помощник, который отличается от того, как я это делаю в С#.

Я должен признать, что я еще не понимаю, почему Sequence и Generator используют typealias и не являются общими протоколами (например, IEnumerable<T> в С#). Есть интересная текущая дискуссия об этом различии, поэтому я оставлю несколько ссылок для любопытного ума:

Ответ 2

Я думаю, что вы вводите в заблуждение компилятор Swift (который сейчас немного шелушится). Тип для вашего диапазона 0..self.columns - Range<Int>, который не является Sequence или Collection, поэтому я не думаю, что его можно использовать через map.

Реализация работает для меня:

extension Matrix {
  func getRow(index: Int) -> T[] {
    var row = T[]()
    for col in 0..self.columns {
      row.append(self[index, col])
    }
    return row
  }
}