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

1234567890123456789012345678901234567890123456789012345678901234567890

2019-03-06: Original

*/

object ClosureExample {

  val inc1 = 10
  var inc2 = 20

  // Pure function accessing val inc1 from scope
  def incr1(x: Int) = x + inc1

  // Side-effecting function accessing/mutating var inc2 from scope
  def incr2(x: Int) = {
    val res = x + inc2 // access var in closure
    inc2 = x           // mutate var in closure
    res
  }

  // Apply higher-order argument g to y
  def app(y: Int, g: (Int=>Int)) = g(y)

  def main(args: Array[String]) {
    println("\nPass pure function incr1 to app")
    println(s"inc1           = $inc1")
    println(s"inc2           = $inc2")
    println(s"app(100,incr1) = ${app(100,incr1)}")
    println(s"inc1           = $inc1")
    println(s"inc2           = $inc2")
    println("\nPass side-effecting function incr2 to app")
    println(s"inc1           = $inc1")
    println(s"inc2           = $inc2")
    println(s"app(200,incr2) = ${app(200,incr2)}")
    println(s"inc1           = $inc1")
    println(s"inc2           = $inc2")
  }
}
