Closures in Scala

Scala supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.

import scala.util.control.Breaks._

// This function intSeq returns another function, which
// we define anonymously in the body of intSeq. The
// returned function closes over the variable i to
// form a closure.
def intSeq(): () => Int = {
  var i = 0
  () => {
    i += 1
    i
  }
}

def main(args: Array[String]): Unit = {
  // We call intSeq, assigning the result (a function)
  // to nextInt. This function value captures its
  // own i value, which will be updated each time
  // we call nextInt.
  val nextInt = intSeq()

  // See the effect of the closure by calling nextInt
  // a few times.
  println(nextInt())
  println(nextInt())
  println(nextInt())

  // To confirm that the state is unique to that
  // particular function, create and test a new one.
  val newInts = intSeq()
  println(newInts())
}

To run the program, save it as Closures.scala and use the Scala compiler:

$ scalac Closures.scala
$ scala Closures
1
2
3
1

In this Scala example, we’ve created a closure that behaves similarly to the Go version. The intSeq function returns an anonymous function that closes over the i variable. Each time the returned function is called, it increments and returns the value of i.

The main differences from the Go version are:

  1. Scala uses def to define functions instead of func.
  2. The return type of intSeq is explicitly declared as () => Int, which represents a function that takes no arguments and returns an Int.
  3. We use var for i because it needs to be mutable.
  4. The closure is defined using () => { ... } syntax.
  5. In the main function, we define it as def main(args: Array[String]): Unit to match Scala’s conventions.

The behavior of the program remains the same: it demonstrates how closures capture and maintain state between function calls.