我已经以尾递归和连续传递样式实现了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/

10-09 02:56