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.