Currying/binding with ISO C99
c, currying
Solution
One common solution to this problem is to change the design into this:
double integrate(double (*f)(double, void*), void*,
double lower, double upper, double step);
Here you pass an additional `void *` to `integrate`, and this is being passed back to `f`. This can be used to pass arbitrary data around, in your case you would pass a pointer to `z`, and within the function `f` you would cast the pointer back to its original type and recover the value `z`. This pattern is ubiquitous within C libraries, for example here is the prototype of pthread_create:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Problem
Say I want to implement a numerical integration routine with plain C. That will look something like this: ``` double integrate(double (*f)(double), double lower, double upper, double step)); ``` I often find functions that actually depend on multiple variables, and I want to integrate over the first one. Say I want to integrate this: ``` double func(double x, double z); ``` with respect to `x`. I cannot pass `func` to `integrate` since it has the wrong signature. Now I know the following workarounds, which were employed by us when we took the numerics course: Use C++ I just have used C++ and ist `std::bind` to create a functor (function object) that I could pass to the integration routine. Now I would just use the lambda functions to get it done. Use GCC extension for functions in function With GCC, you can declare a function in a function. So one could do ``` // z is set to some value in this function scope here. double inner(double x) { return func(x, z); } ``` and pass that `inner` to the `integrate` function. That is non-standard and does not feel so well. Use global variables The value of `z` could be stored in a global variable. That would require the function `func` to be editable to use `z` from the global variables instead of the parameter. That might not be possible. Then it also breaks concurrency and is just bad in general. Does a way exist to do with in plain C without breaking something?