Closures in Objective-C

Objective-C supports blocks, which are similar to anonymous functions and can form closures. Blocks are useful when you want to define a function inline without having to name it.

#import <Foundation/Foundation.h>

// This function returns a block, which we define anonymously in the body of intSeq.
// The returned block closes over the variable i to form a closure.
int (^intSeq)(void) {
    __block int i = 0;
    return ^int(void) {
        i++;
        return i;
    };
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // We call intSeq, assigning the result (a block) to nextInt.
        // This block captures its own i value, which will be updated each time we call nextInt.
        int (^nextInt)(void) = intSeq();
        
        // See the effect of the closure by calling nextInt a few times.
        NSLog(@"%d", nextInt());
        NSLog(@"%d", nextInt());
        NSLog(@"%d", nextInt());
        
        // To confirm that the state is unique to that particular block, create and test a new one.
        int (^newInts)(void) = intSeq();
        NSLog(@"%d", newInts());
    }
    return 0;
}

To run the program, compile it with a command like:

$ clang -framework Foundation closures.m -o closures
$ ./closures
2023-06-08 12:34:56.789 closures[12345:67890] 1
2023-06-08 12:34:56.789 closures[12345:67890] 2
2023-06-08 12:34:56.789 closures[12345:67890] 3
2023-06-08 12:34:56.789 closures[12345:67890] 1

In Objective-C, blocks serve a similar purpose to closures in other languages. They allow you to create inline, anonymous functions that can capture and store references to variables from the surrounding scope.

The __block keyword is used to allow the captured variable i to be modified within the block. Without this, i would be captured as a const copy.

The syntax int (^blockName)(void) declares a block that takes no parameters and returns an int. This is equivalent to the func() int signature in the original example.

Note that Objective-C uses NSLog for console output, which includes additional information like timestamp and process ID in its default format.

The last feature of functions we’ll look at for now is recursion, which is also supported in Objective-C.