Swift中使用抛出闭包延迟映射数组的疑问及实现方法
Swift中带抛出闭包的数组延迟映射问题解析
为什么抛出闭包时lazy.map直接返回数组?
Swift标准库的LazySequenceProtocol并没有提供接受抛出闭包的map重载方法。当你传入抛出函数(比如示例中的square)并使用try调用时,编译器会匹配到Array原生的map(_:)方法——这个方法本身就是即时执行的,会直接遍历数组完成映射并返回结果数组,完全绕过了lazy的延迟逻辑。
如何实现带抛出闭包的延迟映射?
下面提供两种实用的实现方式:
方式一:自定义支持抛出的延迟映射序列
模仿标准库LazyMapSequence的结构,我们可以实现一个支持错误处理的延迟序列:
struct LazyThrowingMapSequence<Base: Sequence, Element>: Sequence, IteratorProtocol { private var baseIterator: Base.Iterator private let transform: (Base.Element) throws -> Element init(base: Base, transform: @escaping (Base.Element) throws -> Element) { self.baseIterator = base.makeIterator() self.transform = transform } mutating func next() throws -> Element? { guard let element = baseIterator.next() else { return nil } return try transform(element) } } // 给LazySequence添加扩展,方便链式调用 extension LazySequence { func throwingMap<Element>(_ transform: @escaping (ElementOfBase) throws -> Element) -> LazyThrowingMapSequence<Elements, Element> { return LazyThrowingMapSequence(base: self.elements, transform: transform) } }
使用示例:
let numbers = Array(1...5) func square(_ x: Int) throws -> Int { // 模拟可能抛出错误的场景 if x == 3 { throw NSError(domain: "DemoError", code: 0, userInfo: [NSLocalizedDescriptionKey: "数字3触发错误"]) } return x * x } // 创建延迟序列,此时不会执行任何映射逻辑 let lazySquares = numbers.lazy.throwingMap(square) // 遍历序列时才会触发映射,错误也在此时抛出 do { for try square in lazySquares { print(square) } } catch { print("遍历出错:\(error.localizedDescription)") }
方式二:利用sequence构建延迟序列
如果不想自定义结构体,也可以用标准库的sequence函数快速构建延迟序列:
let numbers = Array(1...5) func square(_ x: Int) throws -> Int { return x * x } var iterator = numbers.makeIterator() // 构建延迟序列,元素类型为Result,方便处理错误 let lazySquares = sequence { guard let num = iterator.next() else { return nil } return Result { try square(num) } } // 遍历触发执行 for result in lazySquares { switch result { case .success(let square): print(square) case .failure(let error): print("出错:\(error)") } }
内容的提问来源于stack exchange,提问作者goofy4224
相关产品推荐
相关产品推荐

