Car*_*ate 2 c functional-programming c11
I'm writing a Linked List implementation and want to create a foreach function. I want to have two versions of this function: one for internal use that iterates over the nodes themselves, and one for the end user that iterates over the data held in the nodes. Since the code will be nearly the same for each, I'd like to define the second version in terms of the first. Right now, I have two typedefs for the functions used to iterate in each version, and the internal version of foreach:
// The internal-use version that takes a node
typedef void(*Foreach_Node_Function)(size_t index, Node* node);
// The end-user version that takes raw data
typedef void(*Foreach_Function)(size_t index, void* data);
void static foreach_node(Linked_List* ll, Foreach_Node_Function f) {
Node* current = ll->head;
for (size_t i = 0; i < length(ll); i++) {
(*f)(i, current);
current = current->next;
}
}
Run Code Online (Sandbox Code Playgroud)
I need to be able to write an adapter that turns a Foreach_Node_Function into a Foreach_Function. If I had access to anonymous functions, this would be trivial. I could have a function close over a Foreach_Function and modify the given data before passing it along. Something like (pretending lambda is a thing):
void foreach(Linked_List* ll, Foreach_Function f) {
Foreach_Node_Function adapted = lambda(size_t i, Node* node) {
// Only pass on the data to f
(*f)(i, node->data);
};
foreach_node(ll, adapted);
}
Run Code Online (Sandbox Code Playgroud)
C doesn't seem to support anonymous functions though unless you're willing to resort to compiler specific hacks, and I can't see how this could possibly be achieved without them.
Is this possible to achieve in C, and if so, how?
Typically when you have a callback function like this, you add an extra void * parameter (often called callback data or user data) which lets the caller pass extra data through to the callback function. So you would have:
typedef void(*Foreach_Node_Function)(size_t index, Node* node, void *userdata);
typedef void(*Foreach_Function)(size_t index, Node* node, void *userdata);
void static foreach_node(Linked_List* ll, Foreach_Node_Function f, void *f_userdata);
Run Code Online (Sandbox Code Playgroud)
Then, you can pass the callback being adapted, and its void * parameter, through to the adapter callback:
struct foreach_node_adapter_userdata {
Foreach_Function f;
void *f_userdata;
};
static void foreach_node_adapter(size_t index, Node *node, void *userdata) {
struct foreach_node_adapter_userdata *adapter_userdata = userdata;
(*adapter_userdata->f)(index, node->data, adapter_userdata->f_userdata);
}
void foreach(Linked_List* ll, Foreach_Function f, void *f_userdata) {
struct foreach_node_adapter_userdata adapter_userdata = {f, f_userdata};
foreach_node(ll, foreach_node_adapter, &adapter_userdata);
}
Run Code Online (Sandbox Code Playgroud)