Investigating time into working out how you would implement a lambda in plain C in itself gives in-site into why Rust lambda are done how they are.
E.g. This is one approach on lambdas in C.
#include <stdio.h>
struct MainLambda1Capture {
int capture1;
};
int main_lambda_1(struct MainLambda1Capture* capture, int arg1) {
return capture->capture1 * 2 + arg1;
}
// Rust: twice<FN:Fn(i32)->i32>(f: FN, x: i32) -> i32
int twice_$$_main_lambda_1(struct MainLambda1Capture* f, int x) {
return main_lambda_1(f, main_lambda_1(f, x));
}
int main()
{
int x = 5;
struct MainLambda1Capture main_lambda_1_capture;
main_lambda_1_capture.capture1 = x;
printf("%d\n", twice_$$_main_lambda_1(&main_lambda_1_capture, 3));
return 0;
}
This is no heap allocations, and memory is handled on the stack. And you can see that a new twice
needs to be constructed for any possible lambda/lambda-capture for it to work. This is why Rust lambdas are done using generics. Rust generics construct a new function for every lambda parameter parameter used by the code. This is also how C++ templates work, it allows you to avoid a GC and even avoid a heap allocation, and your left with using just stack memory which is likely to fit inside the CPU cache giving you amazing speed.