LoginSignup
0
0

Scala - Call by Name & Call by Value (関数パラメータの評価戦略)

Posted at

Call by Name & Call by Value

Call by Name & Call by Value は関数パラメータの評価戦略を指しています。
相違点としては、評価のタイミングにあります。

Call by Value

item description
評価タイミング パラメータ(引数)は関数を渡す前に評価される
動作 パラメータの実際の値が計算され、その結果が関数内で使用される
特徴 パラメータは一度だけ評価され、その評価された値が関数の中で複数回使われても、再評価は行われない

Call by Name

item description
評価タイミング パラメータは関数の中で実際に使用されるまで評価されない
動作 パラメータは関数内で参照されるたびに評価される
特徴 パラメータが関数内で一度も使われなければ、そのパラメータの評価も行われない。
関数内で複数回参照される場合は、その都度評価される。

Sample code

def methodCallByValue(x: Long): Unit = {
  println("Call by value: " + x)
  println("Call by value: " + x)
}

def methodCallByName(x: => Long): Unit = {
  println("Call by name: " + x)
  println("Call by name: " + x)
}

methodCallByValue(System.nanoTime())
methodCallByName(System.nanoTime())


/* output
Call by value: 3529902534708
Call by value: 3529902534708
Call by name: 3529925374833
Call by name: 3529925707125
*/

methodCallByValue -> 一度だけ評価されている
methodCallByName -> xが呼び出されるたびに評価されている

Which Choose?

  • Call by Value

他言語でも一般的に利用されていて馴染み深い
パラメータの評価に副作用がないか、パラメータの評価結果を複数回使用する場合に適している

  • Call By Name

遅延評価が必要な場合や、条件によってパラメータを評価しない場合に有効
例: 短絡評価(short-circuiting)を行う論理演算など

補足事項

  • 短絡評価(short-circuiting)

ブール演算(論理演算)において、結果が最初のオペランドの評価だけで決定できる場合、残りのオペランドを評価しないというテクニック
主にパフォーマンスの最適化や不必要な副作用を避けるために使用されます

def and(a: Boolean, b: => Boolean): Boolean = {
  if (a) b else false
}

def testA(): Boolean = {
  println("testA called")
  false
}

def testB(): Boolean = {
  println("testB called")
  true
}
println(and(testA(), testB())) // testBは呼ばれない

※ 正格評価の場合、論理演算においえて結果を決定するために必要かどうかかからず、全てのオペランドが評価される

参考文献

Scala & Functional Programming Essentials | Rock the JVM
Programming Scala, 3rd Edition

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0