我已经以尾递归和连续传递样式实现了map
。这两个版本非常相似:
var inc = x => ++x;
var xs = [1,2,3,4,5];
var mapR = f => xs => {
var rec = acc => {
acc[acc.length] = f(xs[acc.length]);
return acc.length < xs.length ? rec(acc) : acc;
}
return rec([]);
}
mapR(inc)(xs); // [2,3,4,5,6]
var mapC = f => xs => cc => {
var rec = acc => cc => {
acc[acc.length] = f(xs[acc.length]);
return acc.length < xs.length ? cc(acc)(rec) : acc;
}
return cc(rec([])(rec));
}
mapC(inc)(xs)(console.log.bind(console)); // [2,3,4,5,6]
代替
cc(acc)(rec)
我显然也可以写rec(acc)
。我的结论正确吗,尾递归只是CPS的特例,用mapC
编写的var rec = acc => {...}
是正确的CPS功能吗? 最佳答案
我将用纯CPS编写如下内容:
const inc = x => cont => cont(x+1);
const map = f => xss => cont => {
if (!xss.length) cont([]);
else f(xss[0])(x => map(f)(xss.slice(1))(xs => cont([x].concat(xs))));
};
// or with an accumulator:
const mapA = f => xs => cont => {
const rec = acc => {
if (acc.length >= xs.length) cont(acc);
else f(xs[acc.length])(x => {
acc.push(x);
rec(acc);
});
}
rec([]);
};
尾递归仅仅是CPS的特例吗?
我不会这么说。 CPS与递归根本无关。
但是,CPS通常仅由尾部调用组成,这使堆栈变得多余了-功能如此强大。
关于javascript - 尾递归仅仅是CPS的特例吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35064635/