あるプログラマの日記

プログラマのメモ、出来事、考えたこと、勉強とかの雑記

遅延評価

名前渡し引数(by-name parameter)

名前渡し引数は、メソッド内で引数の名前が実際に使用される時に評価される。
引数が複数回参照される場合は、参照される度に評価される。
引数の型の前に => を付ける。(引数名: => 型)
Scala は通常は、値渡し(関数を呼び出す前に引数が評価される)

scala> def foo(f: => Unit) = { print("head "); f; println(" tail") }
foo: (f: => Unit)Unit

scala> foo(print("foobar"))
head foobar tail

scala> def foo2(f: => Int) = { print("head "); print(f); println(" tail") }
foo2: (f: => Int)Unit

scala> val a = 3
a: Int = 3

scala> val bar = (b: Int) => { print(b); b * 2 }
bar: (Int) => Int = <function1>

scala> foo2(bar(a))
head 36 tail

scala> foo2(a)
head 3 tail

lazy val

val で宣言するフィールドまたはローカル変数の val の前に lazy を指定すると
実際に変数が使用される時に初めて評価されて初期化される。

scala> lazy val x1 = { println("init x1"); 1 }
x1: Int = <lazy>

scala> val x2 = { println("init x2"); 2 }
init x2
x2: Int = 2

scala> x1
init x1
res5: Int = 1

scala> x1
res6: Int = 1

実際に必要となった時に初めて評価されて変数の初期化は1度しか行われない。