Created
June 28, 2018 03:31
-
-
Save pstephens/dc08296018fa5b620cae8226ffe145b8 to your computer and use it in GitHub Desktop.
What would transducers look like in C?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdbool.h> | |
#include <stddef.h> | |
#include <string.h> | |
#include <stdio.h> | |
typedef struct thing thing_t; | |
struct thing { | |
long num; | |
int cnt; | |
thing_t *children; | |
}; | |
typedef bool (*pred_thing)(void *context, thing_t *x); | |
typedef struct lambda_pred_thing { | |
void *context; | |
pred_thing fn; | |
} lambda_pred_thing_t; | |
typedef void (*transducer_thing)(void *context, thing_t *x); | |
typedef struct lambda_transducer_thing { | |
void *context; | |
transducer_thing fn; | |
} lambda_transducer_thing_t; | |
void foreach(thing_t *parent, lambda_transducer_thing_t *next) { | |
for (int i = 0; i < parent->cnt; ++i) { | |
next->fn(next->context, parent->children + i); | |
} | |
} | |
typedef struct lambda_filter_thing { | |
lambda_transducer_thing_t this; | |
lambda_pred_thing_t pred; | |
lambda_transducer_thing_t next; | |
} lambda_filter_thing_t; | |
void filter(lambda_filter_thing_t *context, thing_t *thing) { | |
if (context->pred.fn(context->pred.context, thing)) { | |
context->next.fn(context->next.context, thing); | |
} | |
} | |
void make_filter(lambda_filter_thing_t *context, lambda_pred_thing_t *pred, lambda_transducer_thing_t *next) { | |
memset(context, 0, sizeof(lambda_filter_thing_t)); | |
context->this.context = context; | |
context->this.fn = (transducer_thing) filter; | |
context->pred = *pred; | |
context->next = *next; | |
} | |
void print(char *format, thing_t *thing) { | |
fprintf(stdout, format, thing->num); | |
} | |
void make_print(lambda_transducer_thing_t *lambda, char *format) { | |
memset(lambda, 0, sizeof(lambda_transducer_thing_t)); | |
lambda->context = format; | |
lambda->fn = (transducer_thing) print; | |
} | |
bool thing_is_even(void* context, thing_t* thing) { | |
return thing->num % 2 == 0 ? true : false; | |
} | |
void lambda_test() { | |
thing_t x[5] = { | |
{.num =105, .cnt = 0, .children = NULL}, | |
{.num = 112, .cnt = 0, .children = NULL}, | |
{.num = 201, .cnt = 0, .children = NULL}, | |
{.num = 302, .cnt = 0, .children = NULL}, | |
{.num = 403, .cnt = 0, .children = NULL} | |
}; | |
thing_t parent = {.num = 0, .cnt = 5, .children = x}; | |
lambda_transducer_thing_t print_lambda; | |
make_print(&print_lambda, "-- %ld --\n"); | |
lambda_filter_thing_t filter_lambda; | |
lambda_pred_thing_t filter_pred = {.context = NULL, .fn = thing_is_even}; | |
make_filter(&filter_lambda, &filter_pred, &print_lambda); | |
foreach(&parent, &filter_lambda.this); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment