【问题标题】:How do I return a sequence in Swift?如何在 Swift 中返回一个序列?
【发布时间】:2023-03-12 18:51:01
【问题描述】:

我正在尝试为书中的 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&lt;T&gt;,但我不明白为什么它使用typealias 而不是仅仅定义为Sequence&lt;T&gt; (see also this)。定义返回泛型 Sequence&lt;T&gt; 的方法不起作用:

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

然后我摆脱了&lt;T&gt;(但它应该是通用的吗?):

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 循环中使用?

关于这个问题的更多信息:Associated Type Considered Weird

【问题讨论】:

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


    【解决方案1】:

    Joe Groff suggested 将结果包装在 SequenceOf&lt;T&gt;

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

    确实,这可行,但我们必须将 map 结果包装到一个辅助类中,这与我在 C# 中的做法不同。

    我不得不承认我还不明白为什么 SequenceGenerator 使用 typealias 并且不是通用协议(如 C# 中的 IEnumerable&lt;T&gt;)。关于这个区别正在进行一个有趣的讨论,所以我会留下一些链接给好奇的人:

    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

    【讨论】:

    • 不要忘记 SequenceOf 已从最新版本的 Swift 中删除。
    【解决方案2】:

    我认为你被 Swift 编译器误导了(目前有点不稳定)。您的范围0..self.columns 的类型是Range&lt;Int&gt;,它不是SequenceCollection,所以我认为它不能通过map 使用。

    实现对我有用:

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

    【讨论】:

    • 我会提交雷达文件...但是如何让序列保持惰性?
    • @Dan 他们懒惰吗?如果我对数组执行映射但不对结果执行任何操作,则仍会为所有数组值执行闭包。
    • 奇怪!我想,如果它不返回一个数组,那么它必须是懒惰的。我会检查的。
    • 原来我们需要使用SequenceOf。查看我的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多