如何在Swift中返回序列?

时间:2014-06-10 09:11:28

标签: generics map generator swift for-in-loop

我试图为书中的Matrix示例slightly tweaked to be generic写一个扩展名。
我正在尝试编写一个名为getRow的方法,该方法返回给定行的值序列。

在C#中,我会写这个:

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>({{3} }})。定义返回泛型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循环中使用?

有关此问题的更多信息:see also this

2 个答案:

答案 0 :(得分:10)

Joe Groff suggested将结果包装在SequenceOf<T>

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

确实,这有效,但是我们必须将map结果包装成一个辅助类,这与我在C#中的方式不同。

我必须承认,我还不明白为什么SequenceGenerator使用typealias并且不是通用协议(例如C#中的IEnumerable<T> )。关于这种区别有一个有趣的持续讨论,所以我会留下一些好奇心的链接:

  1. Associated Types Considered Weird
  2. Associated types vs. type parameters - reason for the former?
  3. Abstract Type Members versus Generic Type Parameters in Scala
  4. Generics and protocols

答案 1 :(得分:1)

我认为你被Swift编译器误导了(目前有点不稳定)。您的范围0..self.columns的类型为Range<Int>,不是SequenceCollection,因此我认为不能通过{{1}使用它}。

实施对我有用:

map