0Pricing
Swift Academy · レッスン

カスタム遅延シーケンスの構築

独自の遅延評価シーケンスを作成します。

「カスタム遅延シーケンスの構築」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応の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

プル型シーケンス

カスタムシーケンスはプル型です。つまり、イテレーターを呼び出すたびに、要求されたときだけ次の値を計算します。これはフィボナッチ数列のジェネレーターです:

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 ラッパー

API を公開するときは、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でラップして具体的な型を隠します

コース完了です!次は、クロージャーを詳しく学びます。

よくある質問

「カスタム遅延シーケンスの構築」レッスンは無料ですか?

はい。「カスタム遅延シーケンスの構築」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「カスタム遅延シーケンスの構築」で何を学びますか?

独自の遅延評価シーケンスを作成します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応の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に戻る