我在这样的js中构建了一个y-combinator
const y = f => { const g = self => f(self(self)); return g(g);}
我简化了这个代码
<StackLayout>
<StackLayout class="m-b-10">
<GridLayout rows="*" columns="*, *, *" *ngIf="stockTakeDetailList.length > 0 && !product">
<Label row="0" col="0" text="Name"></Label>
<Label row="0" col="1" text="Qty"></Label>
<Label row="0" col="2" text="Action"></Label>
</GridLayout>
</StackLayout>
<StackLayout *ngIf="stockTakeDetailList.length > 0 && !product">
<ListView [items]="stockTakeDetailList">
<template let-captureItem="item" let-i="index">
<GridLayout rows="*" columns="*, *, *">
<Label row="0" col="0" class="list-group-item" textWrap="true" [text]="captureItem.ProductDetail_Name"></Label>
<Label row="0" col="1" class="list-group-item" [text]="captureItem.Qty"></Label>
<Label row="0" col="2" class="list-group-item font-awesome" text="" (tap)="removeCaptureItem(i)"></Label>
</GridLayout>
</template>
</ListView>
</StackLayout>
</StackLayout>
这得到无限递归。 这两个版本有什么区别?
答案 0 :(得分:1)
如果您不理解两者之间的区别,我会惊讶您实际构建它们。然而,也许是证明两者之间差异的最好方法是遵循他们的评价
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)
好的,y(z)
(其中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-combinators
在这里,我们可以从头开始构建Y-combinator
// 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)))
让我们测试一下
const U = f => f (f)
const Y = U (h => f => f (x => h (h) (f) (x)))
// range :: Int -> Int -> [Int]
const range = Y (f => acc => x => y =>
x > y ? acc : f ([...acc,x]) (x + 1) (y)) ([])
// fibonacci :: Int -> Int
const fibonacci = Y (f => a => b => x =>
x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
console.log(range(0)(10).map(fibonacci))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
或者我最近最喜欢的
// simplified Y
const Y = f => x => f (Y (f)) (x)
// range :: Int -> Int -> [Int]
const range = Y (f => acc => x => y =>
x > y ? acc : f ([...acc,x]) (x + 1) (y)) ([])
// fibonacci :: Int -> Int
const fibonacci = Y (f => a => b => x =>
x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
console.log(range(0)(10).map(fibonacci))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]