Y combinator 的 javascript实现

又研究了一下之前看刘未鹏文章时候没看懂的y combinator,这次好像搞懂了。思路如下

Section 1


我们想写一个递归函数F(x):一系列操作后调用F(x-1)
但是F在声明完成以前不存在F,我们只有构造f,把f作为参数传递给自己实现调用自己
我们写出了f(f,x):一系列操作后调用f(f,x-1)
我们发现f(f, 这里是重复的,如果把这个功能提取出来,它的功能和那个写不出来的F等价
重新定义f,使得f(f)(x):一系列操作后调用f(f)(x-1)
对比理想中F的定义,F(x):一系列操作后调用F(x-1)
到这里,只要F=f(f),之前写不出的F就写出来了

f = function(self){return function(n){if(n==1) return 1;else return n*self(self)(n-1)}}
F = f(f)
console.log(F(5))


注意到在写f的时候定义里出现了f(f),如果把这个也替换成F来写呢?

Section 2


Clear,推倒重写
所以我们假装F已经存在了,仿照前面的f写出了f_gen(F)(x):一系列操作后调用F(x-1)
我们发现f_gen(F)=F
接下来,我们写f。我们的f要有这么个性质,f(f)=F,所以f_gen(f(f))=F
如果这么定义f(f)(x): 一系列操作后调用f_gen(f(f))(x)
带入100后发现,f(f)(100)=f_gen(f(f))(100)=100*f_gen(f(f))(99),既F=f_gen(f(f))=f(f),F就写出来了
这里我们人肉实现了Y combinator,作用是由f_gen生成F,这么做本质是把定义f_gen时本应在传递参数和调用自身时写的f(f)写成了调用F,然后把f(f)的部分转移到f的定义中去。

f_gen = function(Fact){return function(n){if(n==1) return 1;else return n*Fact(n-1)}}
f = function(self){return function(n){return f_gen(self(self))(n)}}
F = f(f)
console.log(F(5))

有点烧脑,clear以后的内容纯属多此一举,clear以前的已经够用了。

Section 3


Y combinator的意义在于可以写匿名递归函数。
clear以前的方案也可以写

console.log(function(f){return f(f)}(function(self){return function(n){if(n==1) return 1;else return n*self(self)(n-1)})(6))

用Y之后,只要写出Y,这里把人肉部分变成代码了

console.log(function(f){return f(f)}(function(f_gen){return function(self){return function(n){return f_gen(self(self))(n)}}}(function(Fact){return function(n){if(n==1) return 1;else return n*Fact(n-1)}}))(7))

到这里,我们可以用2种方法写出匿名递归函数了

end 

 有种说法是Y算子可以找出f(F)=F的不动点F,即Y(f)=F,这个评价有点过誉了,因为Y是我们刻意构造的,f(F)并不对F做运算,f(F)(x)是f(F,x)的装逼写法而已,目的只是为了引用自身。Y并不能真正求解f(x)=x*x的不动点。

转载于:https://my.oschina.net/zbaigao/blog/3059015

猜你喜欢

转载自blog.csdn.net/weixin_34114823/article/details/91926307
y