这句一言来自 『鬼泣』,是 银炎 在 hitokoto.cn 投稿的。
关注
跳至底部

Y combinator

www.rosettacode.org/wiki/Y_combinator

 

In strict functional programming and the lambda calculus, functions (lambda expressions) don't have state and are only allowed to refer to arguments of enclosing functions. This rules out the usual definition of a recursive function wherein a function is associated with the state of a variable and this variable's state is used in the body of the function.

The Y combinator is itself a stateless function that, when applied to another stateless function, returns a recursive version of the function. The Y combinator is the simplest of the class of such functions, called fixed-point combinators.


Task

Define the stateless Y combinator and use it to compute factorials and Fibonacci numbers from other stateless functions or lambda expressions.

C

C doesn't have first class functions, so we demote everything to second class to match.

#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 {
func (*fn) (func, func);
func _;
int num;
} func_t;
 
func new(func(*f)(func, func), func _) {
func x = malloc(sizeof(func_t));
x->fn = f;
x->_ = _; /* closure, sort of */
x->num = 0;
return x;
}
 
func call(func f, func n) {
return f->fn(f, n);
}
 
func Y(func(*f)(func, func)) {
func g = new(f, 0);
g->_ = g;
return g;
}
 
func num(int n) {
func x = new(0, 0);
x->num = n;
return x;
}
 
 
func fac(func self, func n) {
int nn = n->num;
return nn > 1 ? num(nn * call(self->_, num(nn - 1))->num)
: num(1);
}
 
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);
}
 
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;


posted @ 2018-10-05 16:07  Dismason  阅读(103)  评论(0)    收藏  举报