遅延評価
💡 お知らせ: このドキュメントはAIによって翻訳されています。表現に違和感がある場合は、原文(英語)を参照するか、翻訳にご協力ください。
Flix はほとんどの場面で先行評価(Eager evaluation)を用いますが、lazy キーワードを使うことで、適切な場面でプログラマが遅延評価(Lazy evaluation)を選択できるようになっています:
let x: Lazy[Int32] = lazy (1 + 2);
この式は、強制(force) されるまで評価されません:
let y: Int32 = force x;
注意:
lazy構文に与える式は純粋でなければなりません。
注意: すでに評価済みの遅延値を force しても、再度評価されることはありません。
遅延データ構造
遅延評価を利用すると、使用されるのに合わせて評価される遅延データ構造(Lazy data structure)を作ることができます。これにより、無限のデータ構造を作ることさえ可能になります。
例えば次に示すのは、1 ずつ増えていく整数の無限長ストリームを実装したデータ構造です:
mod IntStream {
enum IntStream { case SCons(Int32, Lazy[IntStream]) }
pub def from(x: Int32): IntStream =
IntStream.SCons(x, lazy from(x + 1))
}
これをもとに、map や take といった関数を実装できます:
pub def take(n: Int32, s: IntStream): List[Int32] =
match n {
case 0 => Nil
case _ => match s {
case SCons(h, t) => h :: take(n - 1, force t)
}
}
pub def map(f: Int32 -> Int32, s: IntStream): IntStream =
match s {
case SCons(h, t) => IntStream.SCons(f(h), lazy map(f, force t))
}
例えば:
IntStream.from(42) |> IntStream.map(x -> x + 10) |> IntStream.take(10)
は次を返します:
52 :: 53 :: 54 :: 55 :: 56 :: 57 :: 58 :: 59 :: 60 :: 61 :: Nil
Flix は、この機能やそれ以上の機能をすでに実装済みの DelayList と DelayMap というデータ構造を提供しています:
DelayList.from(42) |> DelayList.map(x -> x + 10) |> DelayList.take(10)