Javascript中匿名函数的递归调用

self) => (n) => func_gen(self(self))(n) console.log(weirdFunc(fact_gen)(weirdFunc(fact_gen))(5)) //120// 此时我们就得到了一种Y组合子的形式了const Y_ = (gen) => (f) => (n)=> gen(f(f))(n)// 构造一个阶乘递归也很easy了const factorial = Y_(fact_gen) console.log(factorial(factorial)(5)) //120// 但上面这个factorial并不是我们想要的// 只是一种fact2,fact3,fact4的形式// 我们肯定希望这个函数的调用是factorial(5)// 没问题,我们只需要把定义一个 f' = f(f) = (f)=>f(f)// eg. const factorial = fact2(fact2)const Y = gen => n => (f=>f(f))(gen)(n) console.log(Y(fact2)(5)) //120 console.log(Y(fact3)(5)) //120 console.log(Y(fact4)(5)) //120

推导到这里,是不是已经感觉到脊背嗖凉了一下,反正笔者我第一次接触在 康托尔、哥德尔、图灵——永恒的金色对角线 这篇文章里接触到的时候,整个人瞬间被这种以数学语言去表示程序的方式所折服。

来,我们回忆下,我们最终是不是得到了一个不定点算子,这个算子可以找出一个高阶函数的不动点 f(Y(f)) = Y(f) 。 将一个函数传入一个算子(函数),得到一个跟自己功能一样,但又并不是自己的函数,这个说法有些拗口,但又味道十足。

好了,我们回到最初的问题,怎么完成匿名函数的递归呢?有了Y组合子就很简单了:

/*求不动点*/(f => f(f))/*以不动点为参数的递归函数*/(fact => n => n <= 1 ? 1 : n * fact(fact)(n - 1)) /*递归函数参数*/ (5)// 120