遅延評価と即時評価のトレードオフ
遅延評価が有効な場面と不利になる場面を理解します。
「遅延評価と即時評価のトレードオフ」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。
万能な近道はありません
遅延評価が常に高速とは限りません。先行するメモリ確保を、アクセスごとのオーバーヘッドと引き換えにし、副作用が実行されるタイミングも変えます。このトレードオフを理解すれば、適切な方法を選べます。
遅延評価が有利な場合:一部だけ利用する
巨大な変換結果の一部だけが必要な場合、遅延評価なら残りをスキップできます —:
let data = Array(1...1_000_000)
let top = data.lazy.map { $0 * 2 }.prefix(3)
print(Array(top)) // [2, 4, 6] -- 999,997 transforms skipped先行評価が有利な場合:何度も再利用する
結果を何度も反復する場合、先行評価なら一度だけ計算します。遅延評価では反復するたびに再計算します:
let doubled = [1, 2, 3].map { $0 * 2 } // computed once
print(doubled.reduce(0, +)) // 12
print(doubled.max()!) // 6 -- no recompute遅延評価では再計算されます
同じ遅延ビューでも、反復するたびに処理が再実行されます:
var work = 0
let view = [1, 2, 3].lazy.map { (n: Int) -> Int in work += 1; return n }
_ = view.reduce(0, +)
_ = view.max()
print(work) // 6 -- transformed twice要素ごとのオーバーヘッド
遅延評価の各ステップでは、シーケンスを別の型でラップし、要素ごとにクロージャーを呼び出します。小さな配列では、このオーバーヘッドが削減できるメモリ確保のコストを上回ることがあります。
小さな配列なら先行評価で問題ありません
少数の要素をすべて利用する場合は、通常の先行評価を選ぶのが適しています — コードが単純で、メモリ確保のコストもごくわずかだからです:
let nums = [3, 1, 2]
let sorted = nums.map { $0 + 1 }.sorted()
print(sorted) // [2, 3, 4]副作用が実行されるタイミングは異なります
遅延評価では、クロージャー本体は定義した行より後で実行されます。遅延変換の中の副作用に依存する処理は避けてください:
var log: [Int] = []
let v = [1, 2].lazy.map { (n: Int) -> Int in log.append(n); return n }
print(log) // [] -- nothing ran yet
_ = Array(v)
print(log) // [1, 2]先行評価を強制する操作
操作によっては、どのみちシーケンス全体を読み取る必要があるため、遅延評価のメリットがありません:
let nums = Array(1...10)
print(nums.lazy.map { $0 * 2 }.sorted()) // sorted must see all -> [2,4,...,20]
print(nums.lazy.map { $0 }.count) // count walks everything遅延評価と contains
contains(where:)のように途中で処理を打ち切れる操作は、大きな入力に対して遅延評価の恩恵を受けます:
let big = Array(1...1_000_000)
let found = big.lazy.map { $0 * 2 }.contains { $0 == 8 }
print(found) // true -- stops at element 4判断のチェックリスト
次の場合は遅延評価を使います:元のデータが大きく、必要な一部(prefix / first / contains)だけを残し、1回だけ反復する場合です。次の場合は先行評価を使います:配列が小さい場合、結果を再利用する場合、または細かな最適化より読みやすさを重視する場合です。
let huge = Array(1...100_000)
let first = huge.lazy.filter { $0 % 9973 == 0 }.first
print(first!) // 9973推測せずに計測する
パフォーマンスに関する直感は、間違っていることがよくあります。重要な場合は、遅延評価を採用する前に、現実的なデータで両方のバージョンをベンチマークしてください。
let nums = Array(1...50)
let eager = nums.filter { $0 > 25 }.count
let lazyC = nums.lazy.filter { $0 > 25 }.count
print(eager == lazyC) // true -- same answer, profile for speedクイックチェック
遅延評価より先行評価を選ぶべきなのは、どのような場合ですか?
まとめ
次のトレードオフを学びました:
- 大きなデータソースから一部だけを1回の反復で利用する場合は、遅延評価が有利です
- 小さな配列や結果を再利用する場合は、先行評価が有利です(遅延評価では再計算されます)
- 遅延変換内の副作用は後で実行されるため、それに依存しないでください
- 最適化の前に計測してください
次は、カスタム遅延シーケンスの構築です。
よくある質問
「遅延評価と即時評価のトレードオフ」レッスンは無料ですか?
はい。「遅延評価と即時評価のトレードオフ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。
「遅延評価と即時評価のトレードオフ」で何を学びますか?
遅延評価が有効な場面と不利になる場面を理解します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Swift Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「遅延評価と即時評価のトレードオフ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSwift Academyレッスンでコードを書いて実行できますか?
はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- lazyプロパティ
- 遅延評価のmapとfilter
- 遅延評価と即時評価のトレードオフ
- カスタム遅延シーケンスの構築