I am woiking on anoffer C macro mess (inspired by teh cute @pommicket's stronk closure hack) and I figured ouf a pretty nifty pattern in pseudo recursive macros wiff the new c23 features, meowf. Say fur example we wanted to write a functional map macro:
#define MAP(F, ...) ???
Becaufe of how the preprocessor specially in relation to recursion it is pretty trick to do this, buf here's how I've been doink it:
#define MAP(F, ...)\
MAP_IMPL##__VA_OPT__(0)(F __VA_OPT__(,) __VA_ARGS__)
#define MAP_IMPL(F) // terminating state
#define MAP_IMPL0(F, X, ...)\
F(X) MAP_IMPL##__VA_OPT__(1)(F __VA_OPT__(,) __VA_ARGS__)
#define MAP_IMPL1(F, X, ...)\
F(X) MAP_IMPL##__VA_OPT__(2)(F __VA_OPT__(,) __VA_ARGS__)
#define MAP_IMPL2(F, X, ...)\
F(X) MAP_IMPL##__VA_OPT__(3)(F __VA_OPT__(,) __VA_ARGS__)
#define MAP_IMPL3(F, X, ...)\
F(X) MAP_IMPL##__VA_OPT__(4)(F __VA_OPT__(,) __VA_ARGS__)
#define MAP_IMPL4(F, X, ...)\
F(X) MAP_IMPL##__VA_OPT__(5)(F __VA_OPT__(,) __VA_ARGS__)
// ....
Note how teh only thing that changes in each iteration of teh MAP_IMPL macro is the number in front of the name and the argument to __VA_OPT__. VA_OPT fur those not in the know is a new feature that expands its argument only if there's arguments left in teh "...", so the code basically says "As long as there is an element, proceed to a new iteration"
Buf I think teh best part is that all of them will automatically fall back to the unnumbered macro as soon as any of them runs out of arguments, hehe. No need to worry aboot complicated conditional logic and special casing each iteration, them all go there and it jusf works. (also this pattern is supper easy to autogen, so that's anoffer plus)
Littel MAP showcase as bonus, wiff a Reduce:
#define SQUARE(X) ,(X*X)
#define SUM(X,Y) (X+Y)
int main() {
printf("Macro power! %4d;\n", REDUCE(SUM, 2, 2, 4));
printf("Meowf!! %4d;\n", REDUCE(SUM, MAP(SQUARE, 2, 2, 4)));
return 0;
}
Macro power! 8;
Meowf!! 24;
Online: https://onlinegdb.com/UI6Po0ztm
Andf a sneak peek at teh thing I am actually working on:
DEF_CLOSURES(void, int)
DEF_CLOSURES(int, int, int)
void print_int(int x) {
printf("%d\n", x);
}
int add(int a, int b) {
return a + b;
}
int main() {
auto print10 = CLOSURE(1,void,int)(0, print_int, 10);
auto add10 = CLOSURE(1,int,int,int)(0, add, 10);
auto do_add = CLOSURE(2,int,int,int)(0, add, 10, 20);
print10();
printf("some adds!!: %d, %d\n", add10(5), do_add());
return 0;
}
10
some adds!!: 15, 30