Closures in Squirrel

Java 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 java.util.function.Supplier;

public class Closures {

    // This method returns another function, which we define anonymously
    // in the body of intSeq. The returned function closes over the
    // variable i to form a closure.
    public static Supplier<Integer> intSeq() {
        final int[] i = {0};
        return () -> {
            i[0]++;
            return i[0];
        };
    }

    public static void main(String[] args) {
        // 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.
        Supplier<Integer> nextInt = intSeq();

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

        // To confirm that the state is unique to that
        // particular function, create and test a new one.
        Supplier<Integer> newInts = intSeq();
        System.out.println(newInts.get());
    }
}

To run this program:

$ javac Closures.java
$ java Closures
1
2
3
1

In Java, we use the Supplier<Integer> interface to represent a function that takes no arguments and returns an integer. This is similar to the function type func() int in the original example.

The intSeq method returns a Supplier<Integer> that increments and returns a counter. We use an array with a single element to hold the counter because Java requires variables used in lambda expressions to be effectively final.

The main method demonstrates how closures work by creating and using these functions.

The last feature of functions we’ll look at for now is recursion.