本文借助阶乘函数,在javascript中推导了Y combinator。
原始的阶乘函数定义
var fact=function(n){
return n==0?1:n*fact(n-1);
};
console.assert(fact(5)==120);
把递归函数作为参数传递
var highFact=function(f){
return function(n){
return n==0?1:n*f(f)(n-1);
};
};
console.assert(highFact(highFact)(5)==120);
借助辅助函数消除对自身的调用
var fact=(function(g){
return g(g);
}(function(f){
return function(n){
return n==0?1:n*f(f)(n-1);
};
}));
console.assert(fact(5)==120);
构造递归原型
var fact=(function(g){
return g(g);
}(function(f){
return function(n){
var factProto=function(h){
return function(x){
return x==0?1:x*h(x-1);
};
};
return factProto(f(f))(n);
};
}));
console.assert(fact(5)==120);
将递归原型提取出来
var factProto=function(h){
return function(x){
return x==0?1:x*h(x-1);
};
};
var fact=(function(g){
return g(g);
}(function(f){
return function(n){
return factProto(f(f))(n);
};
}));
console.assert(fact(5)==120);
把递归原型变成形参
var fact=(function(k){
return (function(g){
return g(g);
}(function(f){
return function(n){
return k(f(f))(n);
};
}));
}(factProto));
console.assert(fact(5)==120);
得到Y combinator
var yCombinator=function(k){
return (function(g){
return g(g);
}(function(f){
return function(n){
return k(f(f))(n);
};
}));
};
console.assert(yCombinator(factProto)(5)==120);
扩展为多参数形式
var yCombinator=function(k){
return (function(g){
return g(g);
}(function(f){
return function(){
return k(f(f)).apply(null,arguments);
};
}));
};
console.assert(yCombinator(factProto)(5)==120);