记忆化传递延续风格函数

5
我想知道是否有一种实现通用“记忆化”函数的方法(就像Python装饰器中输入为函数,输出为函数),能够处理cps-style函数。
对于普通函数(即“结果值通过返回值返回,参数仅用于输入!”),一个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;
    };
}

但是我的简单memoize函数不能记忆cps风格的函数,因为我需要再次计算类型为函数的参数,并知道要传递给它们的参数。例如,给定以下函数:
function cps(param, next) {
    var ret = param + 1;

    // setTimeout for simulate async behaviour
    setTimeout(function () {
            next(ret);
    }, 0);
}

也许我可以找到next是函数,但它的签名很棘手,而且绝对不是函数中使用的参数!
有人能告诉我我错了吗? :D
我希望能够记忆半打cps风格的函数,而不必在每个函数中插入“缓存”来搞乱逻辑。

如果您将哈希表作为函数参数传递(定义n对键值对),这会简化您的目的逻辑吗? - Fabrizio Calderan
这并不简单:我正在使用cps-style函数,因为我正在处理ajax调用:continueIfTrue / continueIfFalse不是由我的函数直接调用的,而是作为回调函数注册,并在响应返回时由浏览器调用... 我看不出如何使用哈希表可以帮助我(也许我只是瞎了:D启发我吧!)。 - Vito De Tullio
1个回答

2

我是一名新手CPS,但是我认为您需要按照特定方式构建函数。

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

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

    // setTimeout for simulate async behaviour
    setTimeout(function () {
        next(ret);
    }, 0);
}

因此,您可以使用标准的记忆化程序,并构建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);
           }
}

然后可以与记忆化一起使用:

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

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

cpsMemPlusOne(3,function(n){console.log(n)});

重点是将变换的记忆化与 CPS 构造分离开来。
感谢您介绍了记忆化 CPS 的想法;即使这个答案很烂,它也让我大开眼界!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接