Lambdas/Closures module
This module provides as-ergonomic-as-possible Lambda/Closure facilities for C. Defining, binding, freeing, and otherwise working with lambdas (even when using a custom allocator) is made as simple as possible.
"Hello, World!" with Lambdas Example:
// we need to name our lambda type in order to take it as a function parameter // (otherwise we'll get incompatible struct errors trying to bind different anonymous structs to // the function parameter) typedef Lambda(void, CnxString) LambdaVoidString; // declare a lambda function named greet_place that returns `void` and takes in a `CnxString` void LambdaFunction(greet_place, CnxString greeting) { // Retrieve the variable bindings from the lambda. // The binding types (`CnxString` here) and the types of the variables passed // to the generator macro (`lambda` or `lambda_with_allocator`) // __**MUST MATCH**__ let binding = lambda_binding(CnxString); // get the first bound variable let place = binding._1; println("{}, {}!", greeting, place); } void greet_with_hello(LambdaVoidString lambda) { // call the lambda with "Hello" as the `greeting` lambda_call(lambda, cnx_string_from("Hello")); // Free the memory associated w/ the lambda // This will release the binding, and the lambda will no longer be valid lambda_free(lambda); } // Prints "Hello, World!" void hello_world(void) { let world = cnx_string_from("World"); // lambdas capture by value, so if you need to bind a pointer, // take the address of the variable. // The types of the arguments captured __**MUST MATCH**__ those used // in the binding retrieval in the LambdaFunction's definition // This binds `world` as the `CnxString` used as `place` in the // `LambdaFunction`'s definition let lambda = lambda(greet_place, world); // lambdas are generated as anonymous structs for brevity, so we have to cast them // to the named type to pass them to a function or store them greet_with_hello(lambda_cast(lambda, LambdaVoidString)); } // Prints "Hello, C Programmers!" void hello_c_programmers(void) { // multiple lambdas can be bound to a single `LambdaFunction` definition at the same time: // the bound data is separate from the `LambdaFunction`'s definition. // Because lambdas capture by value, they can bind either lvalues or rvalues let lambda = lambda(greet_place, cnx_string_from("C Programmers")); greet_with_hello(lambda_cast(lambda, LambdaVoidString)); }
Typedefs
- using CnxLambdaCaptures = void*
- Stores the captures/bindings of a lambda This is implicitly passed as the first parameter to a
LambdaFunction
, but as a user, will never need to be used or interacted with directly.
Functions
- static void lambda_free(void* lambda)
- Frees the given lambda, freeing associated memory and making it invalid for future use.
Defines
- #define Lambda(ReturnType, ...)
- The type of a complete lambda instance, binding a lambda function definition with a set of captured variables.
- #define LambdaFunction(Name, ...)
- A Lambda function definition. Can be bound to an instance of a lambda with
lambda
orlambda_with_allocator
. - #define LambdaBinding(...)
- A type storing a lambda's bound captures.
- #define lambda_with_allocator(alloc, function_name, ...)
- Binds the given function and captures as a lambda type, that can be called later.
- #define lambda(function_name, ...)
- Binds the given function and captures as a lambda type, that can be called later.
- #define lambda_call(lambda, ...)
- Calls the given lambda with the provided arguments as function parameters.
- #define lambda_clone(lambda)
- Returns a clone of the given lambda, ensuring that (by-value) captures stay valid for the lifetime of the clone.
- #define ScopedLambda
- Declaration tag to scope a lambda, ensuring it is freed when it goes out of scoped and associated resources are cleaned up.
- #define lambda_binding(...)
- Retrieves the bound captures from the enclosing lambda.
- #define lambda_cast(lambda, Type)
- Casts the given lambda to the given named type, so it can be passed to a function or stored.
Typedef documentation
typedef void* CnxLambdaCaptures
#include <include/Cnx/Lambda.h>
Stores the captures/bindings of a lambda This is implicitly passed as the first parameter to a LambdaFunction
, but as a user, will never need to be used or interacted with directly.
Function documentation
static void lambda_free(void* lambda)
#include <include/Cnx/Lambda.h>
Frees the given lambda, freeing associated memory and making it invalid for future use.
Parameters | |
---|---|
lambda | - The lambda to free |
Define documentation
#define Lambda(ReturnType,
...)
#include <include/Cnx/Lambda.h>
The type of a complete lambda instance, binding a lambda function definition with a set of captured variables.
Parameters | |
---|---|
ReturnType | - The return type of the lambda |
... | - The types of the lambda function arguments |
#define LambdaFunction(Name,
...)
#include <include/Cnx/Lambda.h>
A Lambda function definition. Can be bound to an instance of a lambda with lambda
or lambda_with_allocator
.
Parameters | |
---|---|
Name | - The name of the function |
... | - The function argument list |
#define LambdaBinding(...)
#include <include/Cnx/Lambda.h>
A type storing a lambda's bound captures.
Parameters | |
---|---|
... | - The captured variables (or types of the captures) of the lambda binding |
#define lambda_with_allocator(alloc,
function_name,
...)
#include <include/Cnx/Lambda.h>
Binds the given function and captures as a lambda type, that can be called later.
Parameters | |
---|---|
alloc | - The allocator with which to allocate memory to store the captured values in |
function_name | - The function to bind captures to as a lambda |
... | - The list of variables to capture and bind to the lambda |
Returns | a bound lambda |
Binds the given function with the captures list (must capture at least one variable). Captures are captured by value and can be either lvalues or rvalues:
This version uses the provided memory allocator for memory allocation
#define lambda(function_name,
...)
#include <include/Cnx/Lambda.h>
Binds the given function and captures as a lambda type, that can be called later.
Parameters | |
---|---|
function_name | - The function to bind captures to as a lambda |
... | - The list of variables to capture and bind to the lambda |
Returns | a bound lambda |
Binds the given function with the captures list (must capture at least one variable). Captures are captured by value and can be either lvalues or rvalues:
This version uses the default system allocator, DEFAULT_ALLOCATOR
, for memory allocation
#define lambda_call(lambda,
...)
#include <include/Cnx/Lambda.h>
Calls the given lambda with the provided arguments as function parameters.
Parameters | |
---|---|
lambda | - The lambda to call |
... | - The arguments to pass to the lambda function |
Returns | The return value of the lambda function |
#define lambda_clone(lambda)
#include <include/Cnx/Lambda.h>
Returns a clone of the given lambda, ensuring that (by-value) captures stay valid for the lifetime of the clone.
Parameters | |
---|---|
lambda | - The lambda to clone |
Returns | a clone of the lambda |
#define ScopedLambda
#include <include/Cnx/Lambda.h>
Declaration tag to scope a lambda, ensuring it is freed when it goes out of scoped and associated resources are cleaned up.
#define lambda_binding(...)
#include <include/Cnx/Lambda.h>
Retrieves the bound captures from the enclosing lambda.
Returns | The struct containing the bound captures from the enclosing lambda |
---|
#define lambda_cast(lambda,
Type)
#include <include/Cnx/Lambda.h>
Casts the given lambda to the given named type, so it can be passed to a function or stored.
Parameters | |
---|---|
lambda | - The lambda to cast |
Type | - The named Lambda type to cast to. This must be a named typedef in order for the lambda to be able to be passed as a function parameter or stored |
Returns | lambda as Type |