问题 如何在Swift中返回序列?


我正在尝试写一个扩展名 Matrix 书中的例子, 略微调整为通用
我正在尝试编写一个名为的方法 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> (也看到这个)。定义返回泛型的方法 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 循环?

更多关于这个问题: 相关类型被认为是奇怪的


7749
2018-06-10 09:11


起源



答案:


乔格罗夫 建议 包装结果 SequenceOf<T>

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

事实上,这是有效的,但我们必须包装 map 导致一个辅助类,它与我在C#中的方式不同。

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

  1. 相关类型被认为是奇怪的
  2. 关联类型与类型参数 - 前者的原因?
  3. 抽象类型成员与Scala中的泛型类型参数
  4. 泛型和协议

10
2018-06-13 23:38



感谢所有这些链接 - 非常感谢。 - ColinE
不要忘记已从最近版本的Swift中删除了SequenceOf。 - Bohdan Ivanov


答案:


乔格罗夫 建议 包装结果 SequenceOf<T>

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

事实上,这是有效的,但我们必须包装 map 导致一个辅助类,它与我在C#中的方式不同。

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

  1. 相关类型被认为是奇怪的
  2. 关联类型与类型参数 - 前者的原因?
  3. 抽象类型成员与Scala中的泛型类型参数
  4. 泛型和协议

10
2018-06-13 23:38



感谢所有这些链接 - 非常感谢。 - ColinE
不要忘记已从最近版本的Swift中删除了SequenceOf。 - Bohdan Ivanov


我认为你被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
  }
}

1
2018-06-10 09:36



我会提交一个雷达......我怎么保持序列懒惰呢? - Dan Abramov
@Dan他们懒惰吗?如果我在数组上执行映射但不对结果执行任何操作,则仍会对所有数组值执行闭包。 - ColinE
奇怪的!我认为,如果它不返回一个数组,那么它必须是懒惰的。我会检查一下。 - Dan Abramov
原来我们需要使用 SequenceOf。查看我的更新。 - Dan Abramov
感谢更新 - ColinE