0Pricing
Swift Academy · 课时

构建自定义惰性序列

创建您自己的惰性求值序列。

构建自定义惰性序列 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。

为什么要自定义惰性序列

除了 map 和 filter,您还可以构建自己的惰性求值序列,用于无限生成器或昂贵的计算流,让它们按需运行。

LazySequence 类型

调用 .lazy 会将集合包装为符合 LazySequenceProtocol 的类型。您添加的操作会返回更多惰性包装器:

let view = [1, 2, 3].lazy
let mapped = view.map { $0 * 2 }
print(Array(mapped))  // [2, 4, 6]  -- LazyMapSequence

基于拉取的序列

自定义序列基于拉取:迭代器每次被调用时,只会在需要时计算下一个值。下面是一个 Fibonacci 生成器:

struct Fibonacci: Sequence, IteratorProtocol {
    var a = 0, b = 1
    mutating func next() -> Int? {
        let r = a
        (a, b) = (b, a + b)
        return r
    }
}
print(Array(Fibonacci().prefix(6)))  // [0, 1, 1, 2, 3, 5]

无限序列,惰性消费

由于值是按需拉取的,只要截取有限的一部分,无限序列就是安全的:

struct Naturals: Sequence, IteratorProtocol {
    var n = 1
    mutating func next() -> Int? { defer { n += 1 }; return n }
}
print(Array(Naturals().prefix(4)))  // [1, 2, 3, 4]

符合 LazySequenceProtocol

采用 LazySequenceProtocol 后,您自己的类型也可以通过 map/filter 进行惰性链式处理:

struct Counter: Sequence, IteratorProtocol, LazySequenceProtocol {
    var n = 0; let limit: Int
    mutating func next() -> Int? {
        guard n < limit else { return nil }
        defer { n += 1 }
        return n
    }
}
print(Array(Counter(n: 0, limit: 3).map { $0 * 10 }))  // [0, 10, 20]

sequence(first:next:)

标准库提供了一个构建器,无需新建类型即可创建自定义惰性序列:

let powers = sequence(first: 1) { $0 <= 16 ? $0 * 2 : nil }
print(Array(powers))  // [1, 2, 4, 8, 16, 32]

sequence(state:next:)

在各个步骤之间传递更丰富的状态:

let fibs = sequence(state: (0, 1)) { (s: inout (Int, Int)) -> Int? in
    let r = s.0
    s = (s.1, s.0 + s.1)
    return r
}
print(Array(fibs.prefix(6)))  // [0, 1, 1, 2, 3, 5]

AnySequence 包装器

对外提供接口时,可以使用 AnySequence 隐藏具体类型:

func evens(upTo n: Int) -> AnySequence<Int> {
    AnySequence((0...n).lazy.filter { $0 % 2 == 0 })
}
print(Array(evens(upTo: 8)))  // [0, 2, 4, 6, 8]

惰性计算流

将昂贵的工作延迟到每个元素真正被消费时再执行:

let stream = (1...5).lazy.map { (n: Int) -> Int in
    print("computing \(n)")
    return n * n
}
print(stream.first!)  // computing 1, then 1

停止生成器

从 next() 返回 nil,即可干净地结束序列:

let countdown = sequence(state: 3) { (s: inout Int) -> Int? in
    guard s > 0 else { return nil }
    defer { s -= 1 }
    return s
}
print(Array(countdown))  // [3, 2, 1]

整合起来

将自定义生成器与惰性操作组合起来,构建按需运行的管道:

let primesIsh = sequence(first: 2) { $0 < 20 ? $0 + 1 : nil }
    .lazy
    .filter { n in (2..<n).allSatisfy { n % $0 != 0 } }
print(Array(primesIsh))  // [2, 3, 5, 7, 11, 13, 17, 19]

快速检查

什么信号表示自定义 IteratorProtocol 序列已经结束?

回顾

您已经了解了自定义惰性序列:

  • .lazy 会生成 LazySequenceProtocol 包装器
  • 实现 Sequence + IteratorProtocol;next() 返回 nil 以停止序列
  • 使用 sequence(first:next:) / sequence(state:next:) 作为快速构建器
  • 使用 AnySequence 进行包装,以隐藏具体类型

课程完成!下一步:深入学习闭包。

常见问题解答

「构建自定义惰性序列」课时是免费的吗?

是的 — 「构建自定义惰性序列」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。

「构建自定义惰性序列」这节课中我会学到什么?

创建您自己的惰性求值序列。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Swift Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「构建自定义惰性序列」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Swift Academy 课中编写并运行代码吗?

能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. lazy 属性
  2. 惰性 map 与 filter
  3. 惰性与即时求值的权衡
  4. 构建自定义惰性序列
← 返回 Swift Academy