Closures in Fortress

Java supports anonymous functions through lambda expressions, 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 intSeq returns a Supplier<Integer>, which is analogous
    // 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};  // We use an array to hold a mutable int
        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 this Java version, we use a Supplier<Integer> to represent a function that takes no arguments and returns an integer. The intSeq method returns such a Supplier, which increments and returns a captured integer each time it’s called.

The main difference from the original version is that Java doesn’t allow modifying local variables from within lambda expressions. To work around this, we use a single-element array to hold our mutable integer.

The concept of closures is similar in Java and Go, but the syntax and some implementation details differ. In Java, we use lambda expressions and functional interfaces (like Supplier) to achieve similar functionality.

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