Closures in Mercury

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 a Supplier<Integer>, which is similar to a function
    // that takes no arguments and returns an int. The returned Supplier
    // 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 Supplier<Integer>)
        // to nextInt. This Supplier captures its own i value, which
        // will be updated each time we call nextInt.get().
        Supplier<Integer> nextInt = intSeq();

        // See the effect of the closure by calling nextInt.get()
        // 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 Supplier, create and test a new one.
        Supplier<Integer> newInts = intSeq();
        System.out.println(newInts.get());
    }
}

When you run this program, you’ll see:

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 creates a closure by capturing the i variable in the returned lambda expression. Because Java requires variables used in lambda expressions to be effectively final, we use an array with a single element to hold the mutable state.

The main method demonstrates how the closure works. Each call to nextInt.get() increments and returns the captured i value. Creating a new Supplier with intSeq() starts a new sequence, demonstrating that each closure has its own independent state.

This example showcases how Java can use closures to maintain state across multiple invocations of a function, similar to the original example.