Closures in C

Our program demonstrates the concept of function pointers, which can be used to achieve similar functionality to closures in C. Here’s the full source code:

#include <stdio.h>
#include <stdlib.h>

// This structure will hold our "closure" data
typedef struct {
    int i;
    int (*func)(void*);
} intseq_t;

// This function is equivalent to the anonymous function in the original example
int increment(void* data) {
    intseq_t* seq = (intseq_t*)data;
    seq->i++;
    return seq->i;
}

// This function returns a pointer to an intseq_t structure,
// which contains both the state (i) and the function to operate on that state
intseq_t* intSeq() {
    intseq_t* seq = malloc(sizeof(intseq_t));
    seq->i = 0;
    seq->func = increment;
    return seq;
}

int main() {
    // We call intSeq, assigning the result (a pointer to intseq_t)
    // to nextInt. This structure captures its own i value,
    // which will be updated each time we call the function.
    intseq_t* nextInt = intSeq();

    // See the effect of the "closure" by calling the function a few times.
    printf("%d\n", nextInt->func(nextInt));
    printf("%d\n", nextInt->func(nextInt));
    printf("%d\n", nextInt->func(nextInt));

    // To confirm that the state is unique to that
    // particular structure, create and test a new one.
    intseq_t* newInts = intSeq();
    printf("%d\n", newInts->func(newInts));

    // Clean up
    free(nextInt);
    free(newInts);

    return 0;
}

To compile and run the program, use a C compiler like gcc:

$ gcc -o closures closures.c
$ ./closures
1
2
3
1

In this C version, we use a structure intseq_t to hold both the state (i) and a function pointer. This allows us to emulate the behavior of a closure by keeping the state and the function that operates on that state together.

The intSeq function returns a pointer to this structure, initialized with i set to 0 and the function pointer set to our increment function.

In main, we create instances of this structure and call the function through the function pointer, passing the structure itself as an argument. This allows the function to access and modify the state.

While C doesn’t have true closures, this pattern allows us to achieve similar functionality by explicitly managing the state and function together.