牢骚
2017年到了,时间又少了一些,赶快跑起来
正文
昨天过了一下groovy的语法,想起来以前看过的Y组合子,一直感觉没看懂,又找来文章看了看,发现能理解了,在这里总结下
首先介绍两个概念
- 闭包 ,可以理解为匿名方法
- curry,将多元函数降低的过程为curry化 如
f(a,b){return a+b} ;
ff = function(a){
return function(b) {return a+b}
};
f2 = ff(2);
c = f2(3) // c= 5
下来我们要介绍一个情况
var f = function(n){
return n== 1?1 :n*f(n-1);
};
assert f(5) == 120
可以看到我们计算了5的阶乘,利用了递归的思想,但我们引入了一个f,这个f应该是一次性的,被内部引用后无法释放,会污染ns的,有没有办法来解决呢
var f = function(n,self){
return n==1?1: n*self(n-1);
};
assert f(5,self) == 120
看这样如果方法中有一个self的话那么我们应该可以解决引用的问题,这里参数有两个,那么我们用curry化处理下
var f = function(self){
return function(n){
return n==1?1:n * self(self)(n-1);
};
}
f(f)(5) == 120
方法还有self(self) 这种 我们提取出来,放外面
var g = function(h){
var x = function(n){
return h(h)(n);
};
var f = function(self){
return function(n){
return n==1?1:n * self(n-1);
};
};
return f(x);
};
g(g)(5) == 120
把f提出来,再把g包装下
var f = function(self){
return function(n){
return n== 1?1:n*self(n-1);
};
};
var wrap = function(f){
var x = function(n){
return h(h)(n);
};
var g = function(h){
return f(x);
};
return g(g);
};
wrap(f)(5) == 120
wrap就是Y表达式,精简如下
var Y = function(f){
return (function(g){
return g(g);
})(function(h){
return function(){
return h(h).apply(null,arguments);
};
});
};
Y(function(self){
return function(n){
return n==1?1:n*self(n-1);
};
})(5) == 120
这样闭包确实匿名了