Add a rudimentary lambda feature to gnu C23. More...
Go to the source code of this file.
Macros | |
#define | CAPTURE(...) |
Freeze the values of a set of variables in some secret place. | |
#define | LAMBDA(RET, ...) |
Define a lambda with return type RET and argument list __VA_ARGS__ | |
#define | RECAP(...) __VA_OPT__(RECAP_(CAPTURE_NAME(__CAPTURE_COUNT__), __VA_ARGS__)) |
Restore a set values frozen by CAPTURE for the current scope. | |
Add a rudimentary lambda feature to gnu C23.
#define CAPTURE | ( | ... | ) |
Freeze the values of a set of variables in some secret place.
The use of CAPTURE and RECAP usually comes in pairs
Here λ
will use the frozen value of argc
whenever it is called and possible modifications that have been inflicted to argc
are ignored by these calls.
const
-qualified.#define LAMBDA | ( | RET, | |
... | |||
) |
Define a lambda with return type RET
and argument list __VA_ARGS__
Other than a function definition, a lambda is an expression that can be used everywhere where function pointer could be used.
The following lambda
as if an anonymous function were defined somewhere and then the expression would have been replace with a pointer to that function. So a use of that expression in an assignment
has some function
defined in some place, and then replaces the assignment above as if it were written as
This is by itself as presented here is not too interesting.
One point where it becomes interesting is when encapsulated inside a macro that provides a type-generic feature:
The other point that makes this form of lambda interesting is that the lambda has access to local variables of the enclosing function.
Here λ
has access to fact
at each call. Such a feature is difficult to reproduce with a "normal" function, somehow we'd have to know how to provide the information to λ
.
The model of access that is used by this implementation of LAMBDA is that an access to the original variable is made at each call. If for example we'd change fact
between two calls, the second call would see the updated value. We even could modify fact
from within λ
, but that is generally considered to be bad style.
If we want to be sure that the lambda always uses the value of the variable as it is at the point where the lambda is defined, we can use a combination of the CAPTURE and RECAP macros to freeze the values of the used outer variables in place.
Here the invocation of CAPTURE stores the current value of fact
in a safe and immutable place, and then RECAP accesses that stored value and makes it available under the name fact
within κ
, again. Note that the variable fact
in κ
has the same type as the function argument, but that it is in addition const
-qualified and thus cannot be changed.
#define RECAP | ( | ... | ) | __VA_OPT__(RECAP_(CAPTURE_NAME(__CAPTURE_COUNT__), __VA_ARGS__)) |