FailableSequence(可失败序列)

Swift 序列的局限性在于它们不支持带有抛出 `next()` 方法的迭代器。

存在一些需要这种序列的使用场景,例如 FileHandle 和其他数据流在每次读取操作时都可能产生错误。FailableSequence 模块旨在为这些用例提供支持。

Swift 未来可能会内置对可失败序列的支持。请参阅 swift 语言论坛上的讨论。

Sequence 和 Iterator Swift 标准库的一部分已经为 FailableSequence 和 FailableIterator 进行了复制。

一些 Swift 标准库调用(如 map()filter())返回一个 *Array*,而另一些调用(如 drop()prefix())返回一种新的 Sequence 类型。只有当序列很大(或无限…映射一个无限序列效果不佳)时,这种差异才会被注意到。作为 Array 返回调用的替代方案,标准库具有 Sequence.lazy,它提供了对 Sequence 返回调用的访问。

在适当的情况下,FailableSequence 调用与标准库 Sequence.lazy 调用而不是 Sequence 调用匹配。 这样做是为了在检索元素时而不是在构建序列时抛出错误。

有些调用在 Sequence 上可用,但在 FailableSequence 上不可用。 这是因为调用很多,并且实现需要时间。 欢迎提交您需要的调用的任务或拉取请求。

安装

对于 Swift Package

编辑 Package.swift 文件。 将 FailableSequence 添加为依赖项

let package = Package(
    name: " ... ",
    products: [ ... ],
    dependencies: [
        .package(url: "https://github.com/berikv/FailableSequence.git", from: "0.0.2") // here
    ],
    targets: [
        .target(
            name: " ... ",
            dependencies: [
                "FailableSequence" // and here
            ]),
    ]
)

对于 .xcodeproj 项目

  1. 打开菜单 File > Add Packages...
  2. 搜索 "https://github.com/berikv/FailableSequence.git" 并单击 Add Package。
  3. 打开您的项目文件,在 "Targets" 中选择您的目标。
  4. 打开 Dependencies
  5. 点击 + 号
  6. 添加 FailableSequence

用法

使用 firstnext() 创建一个可失败序列。

let sequence = failableSequence(first: 0) { number in
    let next = number + 1
    if next == 3 { throw NumberIsThreeError() }
    return next
}

var numbers = [Int]()
var theError: Error?

do {
    try sequence.forEach { numbers.append($0) }
} catch {
    theError = error
}

// numbers == [0, 1]
// error is NumberIsThreeError

从另一个序列创建一个惰性的可失败 map。

let sequence = (0..<4).failableMap { number -> Int in
    let next = number + 1
    if next == 3 { throw NumberIsThreeError() }
    return next
}

var numbers = [Int]()
var theError: Error?

do {
    try sequence.forEach { numbers.append($0) }
} catch {
    theError = error
}

// numbers == [1, 2]
// error is NumberIsThreeError

从 FailableSequence 创建一个数组。

// Note, if this sequence would cause the *Array init* to throw an error if number == 3.
let sequence = failableSequence(first: 0) { number in
    let next = number + 1
    if next == 3 { throw NumberIsThreeError() }
    return next
}

let array = try Array(sequence.prefix(2))
// array == [0, 1]

请注意,抛出错误不会结束序列。

let sequence = (0...4).failableMap { number -> Int in
    let next = number + 1
    if next == 3 { throw NumberIsThreeError() }
    return next
}

let array = Array(sequence.skipOnThrowSequence)
// array == [1, 2, 4, 5]

贡献

确保您的代码经过充分测试。 运行 ./coverage.sh 以获得概览。

许可证

在 MIT 许可下获得许可。 请参阅 license.md