Functional programming in C with macro "Higher Order Function" generators
c, c-preprocessor, functional-programming
Solution
If you are on Linux/BSD Unix, take a look at queue(3) and check into `/usr/include/sys/queue.h` - it's been done before :)
Problem
Pay attention carefully because this is a hell of a question ;-) I want to use template functions for generic collection actions (like search, foreach, etc.) in C while maintaining compiler static type checking. It is fairly straightforward while you're using simple callbacks like in this example: ``` #define MAKE_FOREACH(TYPE)\ void foreach_##TYPE (TYPE[n] array, int n, void(*f)(TYPE)) {\ for(int i = 0; i < n; i++) {\ f(array[i]);\ }\ } ``` so you can do things like: ``` MAKE_FOREACH(int) MAKE_FOREACH(float) void intcallback(int x){ printf("got %d\n", x); } void floatcallback(float x){ printf("got %f\n", x); } int main(){ int[5] iarray = {1,2,3,4,5}; float[5] farray = {1.0,2.0,3.0,4.0,5.0}; foreach_int(iarray, 5, intcallback); foreach_float(farray, 5, floatcallback); } ``` If I'd like to implement callbacks with return types, for example to make a "map" function, I could do: ``` #define MAKE_MAP(TYPE, RTYPE)\ RTYPE* map_##TYPE (TYPE[n] array, int n, RTYPE(*f)(TYPE)) {\ RTYPE* result = (RTYPE*)malloc(sizeof(RTYPE)*n);\ for(int i = 0; i < n; i++) {\ result[i]=f(array[i]);\ }\ } ``` So far, so good. The problem comes now, when I want my callback functions to accept any number of typed arguments. The idea is something like: ``` #define MAKE_MAP(TYPE, RTYPE, ...)\ RTYPE* map_##TYPE (TYPE[n] array, int n, RTYPE(*f)(TYPE, __VA_ARGS__), __VA_ARGS__) /*this would work for the declaration (because just the types would be enough) but the parameter names are missing :-s*/ \ {\ RTYPE* result = (RTYPE*)malloc(sizeof(RTYPE)*n);\ for(int i = 0; i < n; i++) {\ result[i]=f(array[i], /*here the names of the parameters, in order*/);\ }\ } ``` so, as you can see, I could declare a map function as: ``` MAKE_MAP(int, float, char) ``` giving: ``` float* map_int(int[n] array, int n, float(*f)(int, char), char); ``` but I cannot figure how to implement the parameter passing with the preprocessor. Here is where I ask for your help, ideas and suggestions. (By the way, don't tell me to use a variadic function as template and passing a va_list argument to the callback, because all this stuff was because of the type checking :-p)