Scalaの名前渡しと遅延評価

「名前渡し引数 ≠ lazy だぞー!!! 名前渡しは再計算されるから、間に合わなくなっても知らんぞー!!!」

お題は竹内関数と呼ばれているもの。
Scala2.9にて。

object Main extends App {
  def tarai(x: => Int, y: => Int, z: => Int): Int = {
    if (x <= y) y
    else tarai(
      tarai(x - 1, y, z),
      tarai(y - 1, z, x),
      tarai(z - 1, x, y)
    )
  }

  println(tarai(
    { println("call"); 100 },
    { println("call"); 50 },
    { println("call"); 0 }
  ))
}

出力

call
call
call
call
call
/* 略(かなり長い) */
call
call
call
call
call
100

こうすればOK。

object Main extends App {
  def tarai(nx: => Int, ny: => Int, nz: => Int): Int = {
    lazy val x = nx
    lazy val y = ny
    lazy val z = nz
    if (x <= y) y
    else tarai(
      tarai(x - 1, y, z),
      tarai(y - 1, z, x),
      tarai(z - 1, x, y)
    )
  }

  println(tarai(
    { println("call"); 100 },
    { println("call"); 50 },
    { println("call"); 0 }
  ))
}

出力

call
call
call
100