javascript中的y-combinator

javascript中的y-combinator,javascript,functional-programming,y-combinator,Javascript,Functional Programming,Y Combinator,我在js中构建了一个y-combinator,如下所示 const y = f => { const g = self => x => f(self(self))(x); return g(g);} 我把代码简化成这样 const y = f => { const g = self => f(self(self)); return g(g);} 这将得到一个无限递归。 这两个版本有什么不同 如果你不理解这两者之间的区别,我会很惊讶你居然建造了它们。然而,也许证

我在js中构建了一个y-combinator,如下所示

const y = f => { const g = self => x => f(self(self))(x); return g(g);}
我把代码简化成这样

 const y = f => { const g = self => f(self(self)); return g(g);}
这将得到一个无限递归。
这两个版本有什么不同

如果你不理解这两者之间的区别,我会很惊讶你居然建造了它们。然而,也许证明两者之间差异的最好方法是遵循他们的评估

const y = f => {
  const g = self => x => f(self(self))(x)
  return g(g)
}

y (z) ...
// (self => x => z(self(self))(x)) (self => x => z(self(self))(x)) ...
// returns:
// x => z((self => x1 => z(self(self))(x1))(self => x2 => z(self(self))(x2)))(x)
好的,这里z是一个函数,它返回一个函数x=>。。。。在我们应用这个函数之前,评估就到此为止

现在让我们将其与第二个定义进行比较

const y = f => {
  const g = self => f(self(self))
  return g(g)
}

y (z) ...
// (self => z(self(self))) (self => z(self(self)))
// z((self => z(self(self)))(self => z(self(self)))) ...
// z(z((self => z(self(self)))(self => z(self(self))))) ...
// z(z(z((self => z(self(self)))(self => z(self(self)))))) ...
// z(z(z(z((self => z(self(self)))(self => z(self(self))))))) ...
// ... and on and on
因此,y z永远不会终止——至少在使用应用程序顺序求值的JavaScript中是如此——在应用被调用函数之前先求值函数参数

交替Y组合子

在这里,我们可以从头开始构建Y组合子

// standard definition
const Y = f => f (Y (f))

// prevent immediate infinite recursion in applicative order language (JS)
const Y = f => f (x => Y (f) (x))

// remove reference to self using U combinator
const U = f => f (f)
const Y = U (h => f => f (x => h (h) (f) (x)))

第一个是懒惰。因为Javascript是经过严格评估的,所以您需要冗余的x=>f…x,而不仅仅是f。。。防止无限递归。第一个实际上是z组合子。我引用了这个答案。。。