Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functional programming in C with macro "Higher Order Function" generators

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)

like image 785
fortran Avatar asked May 21 '09 17:05

fortran


People also ask

What is a higher order function in functional programming?

A higher order function is a function that takes a function as an argument, or returns a function . Higher order function is in contrast to first order functions, which don't take a function as an argument or return a function as output. Earlier we saw examples of . map() and . filter() .

Can we use macro for function in C?

In C, function-like macros are much similar to a function call. In this type of macro, you can define a function with arguments passed into it. TechVidvan Tutorial: Macros with arguments! In the above example, the compiler finds the name of the macro (AREA(a)) and replaces it with the statement (a*a).

What is macro over function in C?

A macro is a name given to a block of C statements as a pre-processor directive. Being a pre-processor, the block of code is communicated to the compiler before entering into the actual coding (main () function). A macro is defined with the pre-processor directive.

Which languages support higher order functions?

Prominent examples of languages supporting this are Wolfram Language, C#, Java, ECMAScript (ActionScript, JavaScript, JScript), F#, Haskell, Lisp (Common Lisp, Scheme, Clojure, others), Lua, Oz, Perl, PHP, Prolog, Python, Ruby, Smalltalk, Scala, ML, and Erlang.


1 Answers

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 :)

like image 115
Nikolai Fetissov Avatar answered Sep 24 '22 12:09

Nikolai Fetissov