0Pricing
Scala for Backend Engineering & Functional Programming · レッスン

遅延評価の仕組み

必要になったときだけ値を計算します。

「遅延評価の仕組み」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。

遅延性とは

Scalaでは、ほとんどの値はstrictです。つまり、定義した瞬間に計算されます。遅延性はこの動作を反転させます。遅延値は、初めて必要になったときにだけ計算され、それより前に計算されることはありません。

これは、計算コストが高い場合、失敗する可能性がある場合、またはまったく使用されない可能性がある場合に重要です。誰も求めていない処理にコストをかける必要があるでしょうか。

Strict val

通常のvalは、右辺をすぐに評価します。その後一度も読み取らない場合でも同じです。

これを実行すると、"computing"が"after"より前に表示されることを確認できます。処理は定義時に実行されます。

object Demo extends App {
  val x = { println("computing"); 42 }
  println("after")
  println(x)
}

lazy val

valの前にlazyを付けると、初めてアクセスされるまで評価が延期されます。

ここでは最初に"after"が表示され、その後xを読み取ったときだけ"computing"が表示されます。結果もキャッシュされるため、本体が実行されるのは最大1回です。

object Demo extends App {
  lazy val x = { println("computing"); 42 }
  println("after")
  println(x)
  println(x)
}

名前渡しパラメーター

=> Aとして宣言されたパラメーターは名前渡しで渡されます。つまり、引数はメソッド内で使用されるまで評価されません。

これは遅延性の基盤となる仕組みです。LazyListは名前渡しパラメーターを使用するため、要求されるまで末尾が計算されません。

def maybe(cond: Boolean, value: => Int): Int =
  if (cond) value else 0

val r = maybe(false, { println("side"); 99 })
// "side" never prints; value was unused

LazyListの概要

LazyListはScalaの遅延シーケンスです(2.13以降では以前のStreamに置き換わりました)。先頭は即時評価されますが、末尾は遅延評価されます。

要素は必要に応じて生成され、計算後に一度だけメモ化されるため、同じセルが2回計算されることはありません。

val ll = LazyList(1, 2, 3)
println(ll)
// prints LazyList(<not computed>) until forced

評価の強制

LazyListは、評価を強制するまで未評価のままです。toListやforeachを呼び出したり、各要素を表示したりすると、セルの評価が強制されます。

REPLでは、遅延している末尾に<not computed>と表示されます。評価を強制すると実際の値が現れます。

object Demo extends App {
  val ll = LazyList(1, 2, 3)
  println(ll.toList)
}

#::演算子

#::を使うとLazyListの先頭に要素を追加できます。リストの::とは異なり、#::の右オペランドは名前渡しであるため、必要になるまで末尾は構築されません。

これにより、残りの部分を遅延的に計算するシーケンスを記述できます。

val ll = 1 #:: 2 #:: 3 #:: LazyList.empty
println(ll.head)

メモ化

LazyListのセルが一度計算されると、その値が保存されます。もう一度読み取ってもコストはかからず、生成元の式が再度実行されることもありません。

これを実行すると、"calc"は各要素に初めてアクセスしたときだけ表示され、繰り返し読み取っても表示されないことを確認できます。

object Demo extends App {
  val ll = LazyList(1, 2).map { n =>
    println("calc " + n); n * 10
  }
  println(ll.head)
  println(ll.head)
}

遅延する末尾の動作

末尾が遅延するため、LazyListにmapを適用しても、実際にアクセスした要素だけが計算されます。

ここではリストに3つの要素があるにもかかわらず、強制されるのが先頭だけなので、"map"は1回だけ表示されます。

object Demo extends App {
  val r = LazyList(1, 2, 3).map { n =>
    println("map " + n); n + 1
  }
  println(r.head)
}

遅延性の利点

遅延性には、不要な処理を避けること、無限シーケンスを構築すること、計算の記述方法と実行量を切り離すことという3つの利点があります。

パイプライン全体を一度記述し、何個の要素を取得するかは利用側に決めさせることができます。

注意点

遅延性にはコストもあります。LazyListはメモ化するため、先頭への参照を保持すると、強制評価されたすべての要素がメモリに残り続けます。巨大なデータや無限データでは、先頭を保持し続けないようにしてください。

また、遅延コード内の副作用は予期しないタイミングで実行されるため、デバッグを難しくすることがあります。

理解度チェック

遅延評価についての理解度を確認してください。

まとめ

厳格評価では処理がすぐに実行され、遅延評価では必要になるまで延期されます。lazy valと名前渡しパラメーター(=> A)が基本となる仕組みです。

LazyListはこれらを基盤として、即時評価される先頭と、遅延評価されてメモ化される末尾を構築します。評価はtoListや要素へのアクセスによって強制されます。次は、LazyListを手作業で構築します。

よくある質問

「遅延評価の仕組み」レッスンは無料ですか?

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

「遅延評価の仕組み」で何を学びますか?

必要になったときだけ値を計算します。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Scala for Backend Engineering & Functional Programmingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのScala for Backend Engineering & Functional Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「遅延評価の仕組み」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?

はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 遅延評価の仕組み
  2. LazyListを構築する
  3. 無限ストリーム
  4. 遅延的な取得とフィルタリング
← Scala for Backend Engineering & Functional Programmingに戻る