/* CSci 555, Functional Programming, Spring 2019
   Thunk Example

1234567890123456789012345678901234567890123456789012345678901234567890

2019-03-06: Original
*/
object ThunkExample {
  val x = 10
  var y = 20

  // By-name argument exp, evaluated for each access
  def test1(exp: =>Int): Int = {
    println(s"In test1, evaluating argument exp = $exp")
    exp  // evaluate by-name argument exp and return its value
  }

  // By-name argument z, evaluated for each access
  def test2(k: Int, z: =>Int): Int = {
    var res = 0
    for(i <- 1 to k) { // evaluate z k times
      res += z         // add z's values
    }
    res  // return res
  }

  def main(args: Array[String]) {
    println(s"x           = $x")
    println(s"y           = $y")
    println(s"test1(x+y)  = ${test1(x+y)}")
    println(s"x           = $x")
    println(s"y           = $y")
    println("Set y to 200")
    y = 200
    println(s"x           = $x")
    println(s"y           = $y") 
    println(s"test1(x+y)  = ${test1(x+y)}")
    println(s"x           = $x")
    println(s"y           = $y") 
    println("Using test2, k = 3")
    println(s"test2(3,test1(x+y)) = ${test2(3,test1(x+y))}")
    println(s"x           = $x")
    println(s"y           = $y") 
    println("Set y to 2")
    y = 2
    println(s"x           = $x")
    println(s"y           = $y") 
    println("Using test2, k = 5")
    println(s"test2(3,test1(x+y)) = ${test2(5,test1(x+y))}")
    println(s"x           = $x")
    println(s"y           = $y") 
  }
}
