繁体   English   中英

使用抛出闭包延迟映射数组

[英]Lazily Mapping an Array Using a Throwing Closure

当延迟映射值数组时,我按预期收到类型为LazyMapSequence的实例:

Welcome to Apple Swift version 5.7 (swiftlang-5.7.0.127.4 clang-1400.0.29.50).
Type :help for assistance.
  1> let numbers = Array(1...5)
numbers: [Int] = 5 values {
  [0] = 1
  [1] = 2
  [2] = 3
  [3] = 4
  [4] = 5
}
  2> let squares = numbers.lazy.map { $0 * $0 }
squares: LazyMapSequence<LazySequence<[Int]>.Elements, Int> = {
  _base = 5 values {
    [0] = 1
    [1] = 2
    [2] = 3
    [3] = 4
    [4] = 5
  }
  _transform =
}

但是,如果map(_:)方法接收到一个抛出闭包,映射就不会延迟执行,我接收到一个数组:

  3> func square(_ x: Int) throws -> Int {
  4.     return x * x
  5. }
  6> let squares = try numbers.lazy.map(square)
squares: [Int] = 5 values {
  [0] = 1
  [1] = 4
  [2] = 9
  [3] = 16
  [4] = 25
}

这是为什么,我如何使用抛出闭包懒惰地 map 值数组?

解决方法是

extension LazySequennce {
    func tryMap<U>(_ transform: @escaping (Self.Element) throws -> U) -> LazyMapSequence<Self.Elements, Result<U, Error>> {
        self.map { x in Result(catching: { try transform(x) }) }
    }
}

请注意,序列的元素类型是Result<U, Error> 无论何时抛出任何错误,我们基本上都会“捕获”错误。 必须捕获错误,因为在遍历任何Sequence时,协议要求不抛出任何错误。

至于为什么map(square)不偷懒,正如你观察到的那样。 LazySequenceProtocol.map采用不抛出的闭包。

func map<U>(_ transform: @escaping (Self.Element) -> U) 
    -> LazyMapSequence<Self.Elements, U>

当您传入 throwing 方法时,它会调用Sequence.map

func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]

这不是懒惰。

如果有一个看起来像这样的方法,这一切都会得到解决:

func tryMap<U>(_ transform: @escaping (Self.Element) throws -> U) 
    -> LazyThrowingMapSequence<Self.Elements, U>

但是,这样的LazyThrowingMapSequence类型不能符合Sequence ,因为它的迭代器不能符合IteratorProtocol 它的迭代器的next方法抛出,但IteratorProtocol要求next不抛出。

理论上可以通过在LazyThrowingMapSequence的几个地方添加throws来编写LazyMapSequence LazyMapSequence的源代码在这里)但是使用它会很痛苦,因为你不能用for循环迭代它,而且它没有Sequence协议中的任何方便方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM