Closures in Chapel

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

use IO;

// 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.
proc intSeq() {
  var i = 0;
  return lambda(): int {
    i += 1;
    return i;
  };
}

proc main() {
  // 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.
  var nextInt = intSeq();

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

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

To run the program:

$ chpl closures.chpl -o closures
$ ./closures
1
2
3
1

In this Chapel version, we use the lambda keyword to create an anonymous function. The intSeq procedure returns this lambda function, which forms a closure over the i variable.

The main procedure demonstrates how to use this closure. We create an instance of the closure by calling intSeq() and assign it to nextInt. Each time we call nextInt(), it increments and returns its internal i value.

To show that each closure maintains its own state, we create a new instance newInts and call it once, demonstrating that its counter starts from 1 again.

Chapel’s closures work similarly to those in other languages, allowing you to create functions with persistent local state.