Step 2 of 6
typedef and passing callbacks
Function pointer types are hard to read, so C programmers name them with typedef:
typedef int (*BinOp)(int, int); /* BinOp: pointer to function (int, int) -> int */
Now BinOp can be used like any type, which makes it easy to write functions that take behavior as a parameter. The function you pass in is called a callback, because the receiving function "calls back" into your code.
#include <stdio.h>
typedef int (*Predicate)(int);
static int is_even(int x) { return x % 2 == 0; }
static int is_big(int x) { return x > 100; }
int count_if(const int *a, int n, Predicate p) {
int count = 0;
for (int i = 0; i < n; i++) {
if (p(a[i])) {
count++;
}
}
return count;
}
int main(void) {
int v[] = {4, 150, 7, 200, 10};
printf("%d even, %d big\n", count_if(v, 5, is_even), count_if(v, 5, is_big));
return 0;
}
4 even, 2 big
count_if doesn't know or care what it's counting. It walks the array and asks the callback about each element. One loop now serves every counting question you'll ever have.
Fold (also called reduce)
Fold is the same idea for combining values: keep an accumulator, starting at some initial value, and for each element replace it with f(accumulator, element). With addition and 0 you get a sum; with multiplication and 1 a product; with a "bigger of two" function, a maximum. It's one of the most general loops there is, and languages like C++, Python and JavaScript have it built in (std::accumulate, reduce).
(static on the helper functions just keeps them private to this file, which is covered in the last module of this section.)
Your turn: write fold. It starts with init and combines it with each element in order: acc = f(acc, a[i]).