RosettaCodeData/Task/Y-combinator/C/y-combinator.c

71 lines
1.5 KiB
C
Raw Permalink Normal View History

2013-04-11 01:07:29 -07:00
#include <stdio.h>
#include <stdlib.h>
/* func: our one and only data type; it holds either a pointer to
a function call, or an integer. Also carry a func pointer to
a potential parameter, to simulate closure */
typedef struct func_t *func;
typedef struct func_t {
2017-09-23 10:01:46 +02:00
func (*fn) (func, func);
func _;
2013-04-11 01:07:29 -07:00
int num;
} func_t;
func new(func(*f)(func, func), func _) {
func x = malloc(sizeof(func_t));
2017-09-23 10:01:46 +02:00
x->fn = f;
2013-04-11 01:07:29 -07:00
x->_ = _; /* closure, sort of */
x->num = 0;
return x;
}
2017-09-23 10:01:46 +02:00
func call(func f, func n) {
return f->fn(f, n);
2013-04-11 01:07:29 -07:00
}
func Y(func(*f)(func, func)) {
2017-09-23 10:01:46 +02:00
func g = new(f, 0);
2013-04-11 01:07:29 -07:00
g->_ = g;
return g;
}
func num(int n) {
func x = new(0, 0);
x->num = n;
return x;
}
2017-09-23 10:01:46 +02:00
func fac(func self, func n) {
int nn = n->num;
return nn > 1 ? num(nn * call(self->_, num(nn - 1))->num)
2013-04-11 01:07:29 -07:00
: num(1);
2017-09-23 10:01:46 +02:00
}
2013-04-11 01:07:29 -07:00
2017-09-23 10:01:46 +02:00
func fib(func self, func n) {
int nn = n->num;
return nn > 1
? num( call(self->_, num(nn - 1))->num +
call(self->_, num(nn - 2))->num )
: num(1);
2013-04-11 01:07:29 -07:00
}
void show(func n) { printf(" %d", n->num); }
int main() {
int i;
func f = Y(fac);
printf("fac: ");
for (i = 1; i < 10; i++)
show( call(f, num(i)) );
printf("\n");
f = Y(fib);
printf("fib: ");
for (i = 1; i < 10; i++)
show( call(f, num(i)) );
printf("\n");
return 0;
}