Skip to content

Instantly share code, notes, and snippets.

@louisswarren
Last active October 1, 2021 00:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save louisswarren/0a007b0825ee4f5b94e524e70d5ea7c9 to your computer and use it in GitHub Desktop.
Save louisswarren/0a007b0825ee4f5b94e524e70d5ea7c9 to your computer and use it in GitHub Desktop.
Generators in C
#include <stdio.h>
#define FIRST(N, ...) (N)
#define foreach(X, F, ...) \
for (init_##F(__VA_ARGS__), X = F(FIRST(__VA_ARGS__));\
FIRST(__VA_ARGS__)->_running;\
X = F(FIRST(__VA_ARGS__)))
struct count_state {
int _running;
int n;
};
void
init_count(struct count_state *g, int start)
{
g->_running = 1;
g->n = start;
}
int
count(struct count_state *g)
{
return g->n++;
}
struct range_state {
int _running;
int n;
int start;
int end;
int step;
};
void
init_range(struct range_state *g, int start, int end, int step)
{
g->_running = g->n < g->end;
g->start = start;
g->end = end;
g->step = step;
g->n = start;
}
struct list_iter_state {
int _running;
int *p;
size_t n;
};
int
range(struct range_state *g)
{
int r = g->n;
g->_running = g->n < g->end;
g->n += g->step;
return r;
}
void
init_list_iter(struct list_iter_state *g, int *p, size_t n)
{
g->_running = g->n > 0;
g->p = p;
g->n = n;
}
int
list_iter(struct list_iter_state *g)
{
g->_running = g->n > 0;
g->n--;
return *(g->p++);
}
int
main(void)
{
struct range_state g;
int x;
foreach (x, range, &g, 1, 10, 3) {
printf("%d\n", x);
}
printf("\n");
struct list_iter_state h;
int xs[] = {2, 3, 5, 7, 11};
foreach (x, list_iter, &h, xs, sizeof(xs)/sizeof(xs[0])) {
printf("%d\n", x);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment