memoize延续传递样式功能

Vit*_*lio 5 javascript memoization continuation-passing

我想知道是否有一种方法可以实现通用的"memoize"功能(如在函数中作为输入和函数作为输出,作为python的装饰器)能够处理cps样式的函数.

对于正常函数(如"返回结果值,参数仅用于输入!")memoize函数可以像(在javascript中)一样简单

function memoize(fun) {
    var cache = {};
    return function () {
        var args = Array.prototype.slice.call(arguments);
        if (args in cache)
            return cache[args];
        var ret = fun.apply(this, arguments);
        cache[args] = ret;
        return ret;
    };
}
Run Code Online (Sandbox Code Playgroud)

但是我的简单memoize函数无法记忆cps风格的函数,因为我需要再次"评估"类型函数的参数,同时知道要传递给它们的参数.

例如,给定功能

function cps(param, next) {
    var ret = param + 1;

    // setTimeout for simulate async behaviour
    setTimeout(function () {
            next(ret);
    }, 0);
}
Run Code Online (Sandbox Code Playgroud)

也许我可以发现这next是一个函数,但它的签名(好吧......也许,但它很棘手),绝对不是函数中使用的参数!

有人能告诉我,我错了吗?:d

我有兴趣能够记住六个cps风格的函数,我不想搞乱在每个函数中插入"缓存"的逻辑.

Phi*_*l H 2

我是 CPS 的新手,但我认为您必须以特定的方式构建您的函数。

您的 CPS 函数具有以下结构(从您的示例概括):

function cps(param, next) {
    var ret = someFunctionOfParam(param);

    // setTimeout for simulate async behaviour
    setTimeout(function () {
        next(ret);
    }, 0);
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用标准存储器,并构建 CPS 函数。为了将其分开,首先是 CPS 制造者(假设函数的最后一个参数始终是要传递给的函数):

function cpsMaker(transformFunc) {
    return function() {
               var args = Array.prototype.slice.call(arguments);
               var next = args.pop(); // assume final arg is function to call
               var ret = transformFunc.apply(this,args);
               // setTimeout for simulate async behaviour
               setTimeout(function () {
                   next(ret);
               }, 0);
           }
}
Run Code Online (Sandbox Code Playgroud)

然后memoizer可以与它结合使用:

function plusOne(val) {
    return val+1;
}

var memoPlusOne = memoize(plusOne);
var cpsMemPlusOne = cpsMaker(memoPlusOne);

cpsMemPlusOne(3,function(n){console.log(n)});
Run Code Online (Sandbox Code Playgroud)

重点是将转换的记忆与 CPS 构造分开。

感谢您介绍memoized CPS的思想;即使这个答案是垃圾,但也让我大开眼界!