5

cps スタイルの関数も処理できる一般的な「メモ化」関数 (関数を入力として、関数を出力として、Python のデコレータとして) を実装する方法があるかどうか疑問に思っています。

通常の関数の場合 (「結果の値はリターンによって返されます。パラメーターは入力専用です!」のように) 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;
    };
}

しかし、cps スタイルの関数は単純な関数ではメモ化できません。memoize関数型の引数を「再度」評価する必要があり、それらに渡すパラメーターも知っているからです。

たとえば、次の関数が与えられた場合

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

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

多分私はそれが関数であることを見つけることnextができますが、その署名(まあ...多分、しかしそれはトリッキーです)であり、間違いなく関数で使用されるパラメーターではありません!

誰かが私が間違っていると言うことができますか? :D

半ダースの cps スタイルの関数をメモできることに興味があり、それらのすべてに「キャッシュ」を挿入するロジックを台無しにしたくありません。

4

1 に答える 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 のアイデアを紹介していただきありがとうございます。この答えがゴミだとしても、それは私にとって目を見張るものでした!

于 2012-04-14T20:36:43.143 に答える