如何将 JavaScript 中的以下函数转换为延续传递样式 (CPS)



>假设我有以下函数:

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 中会是什么样子?

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

延续传递风格非常简单。例如,假设您有以下要转换为 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))));

fg不接受任何参数的情况下,它们不是函数(在函数的数学意义上)。因此,它们只是常量:

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 编写常量。想想看:当fg不进行任何争论时,f(g(h()))真的没有任何意义。最好只写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]));
        };
    }
}

希望有帮助。

最新更新