Skip to content

Instantly share code, notes, and snippets.

@nrdmn
Created February 21, 2019 17:37
Show Gist options
  • Save nrdmn/22550351c16ab324a71d1a74963ec4ad to your computer and use it in GitHub Desktop.
Save nrdmn/22550351c16ab324a71d1a74963ec4ad to your computer and use it in GitHub Desktop.
functional C with lambdas and CPS
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <stdbool.h>
#include <stdlib.h>
#define FN void __attribute__((noreturn))
#define LAMBDA(c_) ({ FN _ c_ _;})
struct maybe {
void *data;
bool just;
};
struct cons {
void *data;
struct maybe *next;
};
FN malloc_(FN (*next)(void *), size_t size)
{
void *ptr = malloc(size);
if (ptr == NULL) {
exit(EXIT_FAILURE);
} else {
next(ptr);
}
}
FN map(FN (*next)(struct maybe *), FN (*f)(FN (*)(), void *), struct maybe *l)
{
FN map_(FN (*next)(struct maybe *), FN (*f)(FN (*)(), void *), struct maybe *begin, struct maybe *ptr)
{
if (ptr->just) {
f(LAMBDA(() {
map_(next, f, begin, ((struct cons *)ptr->data)->next);
}), ((struct cons *)ptr->data)->data);
} else {
next(begin);
}
}
map_(next, f, l, l);
}
FN fold(FN (*next)(void *), FN (*f)(FN (*)(void *), void *, void *), void *init, struct maybe *l)
{
if (l->just) {
void *d = ((struct cons *)l->data)->data;
struct maybe *n = ((struct cons *)l->data)->next;
free(l->data);
free(l);
f(LAMBDA((void *x) {
fold(next, f, x, n);
}), init, d);
} else {
free(l);
next(init);
}
}
FN sum(FN (*next)(int *), struct maybe *l)
{
malloc_(LAMBDA((int *init) {
*init = 0;
fold(next, LAMBDA((FN (*f)(void *), int *a, int *b) {
*a += *b;
free(b);
f(a);
}), init, l);
}), sizeof(int));
}
FN list_5_23_42(FN (*next)(struct maybe *))
{
int *five = malloc(sizeof(int));
int *twentythree = malloc(sizeof(int));
int *fortytwo = malloc(sizeof(int));
*five = 5;
*twentythree = 23;
*fortytwo = 42;
struct cons *c = malloc(sizeof(struct cons));
c->data = fortytwo;
c->next = malloc(sizeof(struct maybe));
c->next->data = NULL;
c->next->just = false;
struct cons *b = malloc(sizeof(struct cons));
b->data = twentythree;
b->next = malloc(sizeof(struct maybe));
b->next->data = c;
b->next->just = true;
struct cons *a = malloc(sizeof(struct cons));
a->data = five;
a->next = malloc(sizeof(struct maybe));
a->next->data = b;
a->next->just = true;
struct maybe *l = malloc(sizeof(struct maybe));
l->data = a;
l->just = true;
next(l);
}
FN main()
{
list_5_23_42(LAMBDA((struct maybe *list) {
map(
LAMBDA((struct maybe *l) {
sum(
LAMBDA((int *n) {
assert(*n == 5*5 + 23*23 + 42*42);
printf("%d\n", *n);
free(n);
exit(EXIT_SUCCESS);
}),
l
);
}),
LAMBDA((FN (*next)(), int *n) {
*n *= *n;
next();
}),
list
);
}));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment