2

假设我有以下功能:

function f(x) { return x + 1; }

function g(x) { return x * 2; }

function h() { return 5; }

如何将表达式f(g(h()))转换为延续传递样式?我知道这h会转化为:

function h(ret) { ret(5); }

但是,我不知道如何将表达式f(g(h()))转换为 CPS。

另外,如果f需要 2 个参数而不是 1 个呢?这在 CPS 中会是什么样子?

f此外,如果g根本不接受任何论点怎么办?这在 CPS 中看起来如何?

4

1 回答 1

4

续传风格真的很简单。例如,假设您有以下要转换为 CPS 的函数:

function f(x) {
    return x + 1;
}

function g(x) {
    return x * 2;
}

function h() {
    return 3;
}

alert(f(g(h())));

写在 CPS 中:

function f(k) {
    return function (x) {
        return k(x + 1);
    };
}

function g(k) {
    return function (x) {
        return k(x * 2);
    };
}

function h(k) {
    return k(3);
}

h(g(f(alert)));

何时f接受两个参数:

function f(k) {
    return function (x) {
        return function (y) {
            return k(x + y);
        };
    };
}

function g(k) {
    return function (x) {
        return k(x * 2);
    };
}

function h(k) {
    return k(3);
}

h(h(g(f(alert))));

在这种情况下f并且g不带任何参数,它们不是函数(在函数的数学意义上)。因此,它们只是常量:

function f(k) {
    return k(1);
}

function g(k) {
    return k(2);
}

function h(k) {
    return k(3);
}

h(alert);
g(alert);
f(alert);

无法使用 CPS 组合常量。想一想:f(g(h()))f并且g不接受任何争论时,这真的没有任何意义。最好只写h(), g(), f()

与柯里化结合使用时,延续传递风格特别好:

var f = curry(function (k, x, y) {
    return k(x + y);
});

var g = curry(function (k, x) {
    return k(x * 2);
});

function h(k) {
    return k(3);
}

h(h(g(f(alert))));

function curry(f, l, a) {
    var len = l;
    var args = a;

    switch (arguments.length) {
    case 1: len = f.length;
    case 2: args = [];
    }

    if (args.length + 1 === len) {
        return function (a) {
            return f.apply(null, args.concat([a]));
        };
    } else {
        return function (a) {
            return curry(f, len, args.concat([a]));
        };
    }
}

希望有帮助。

于 2014-12-12T04:18:05.000 回答