7

JS の初心者 :) Crockford の本のセクション 4.15 のコード部分の説明が必要です。

var memoizer = function (memo, fundamental) {
    var shell = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fundamental(shell, n);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};

var fibonacci = memoizer([0, 1], function (shell, n) {
    return shell(n - 1) + shell(n - 2);
});

質問: fibonacci(15) を計算するにはどうすればよいですか? また、単純な fibonacci(15) 呼び出しの場合、詳細はどのように機能しますか?

手伝ってくれてありがとう。

4

4 に答える 4

3

console.log()これは、それぞれの再帰呼び出しごとに、スタックがどのように (n-1)+(n-2) の結果をメモ配列に返し、割り当てるかを示す注釈付きバージョンです。また、スタックが逆の順序で戻ることも覚えておいてください。したがって、ログ出力では、最後の呼び出しが最初に返されたことがわかります。

var memoizer = function (memo, fundamental) {
    var shell = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fundamental(shell, n);
            console.log("Hence 'shell(n-1)+shell(n-2)' results in the assignment memo["+n+"]="+result);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};
var fibonacci = memoizer([0, 1], function (shell, n) {
    console.log("shell is called, and 'n' is equal to --> " + n + "\n" + "At this point shell(n-1)="+shell(n-1)+" AND shell(n-2)="+shell(n-2));
    return shell(n - 1) + shell(n - 2);    
});
于 2015-06-15T21:01:55.850 に答える
2

呼び出しがfibonacci(15)機能する理由について混乱しているようです。コードを単純化しましょう (ちょっとメモ化のことは忘れてください)。

var m = function () {
    var s = function (n) {
        console.log(n);
    };
    return s;
}; 
var f = m();

基本的fに function の戻り値に設定していますm()。この場合、その戻り値は関数です。ほら、次のようにさらに単純化できます。

var f = function (n) { console.log(n); };

つまり、fパラメータを1つ取る関数になるように設定しています。フィビナッチの例でも同じことをしています。それが呼び出しがfibonacci(15)機能する理由です。

于 2015-10-18T02:22:17.443 に答える
1

あなたの質問へのコメントが示唆するように、本の説明に従えない場合は、デバッガーでコードを調べて、何が起こっているのかをよく理解する必要があります。しかし、何が起こっているのかを簡単に説明します。

実証されているのは、関数型プログラミングで使用される一般的な最適化手法である「メモ化」です。結果が渡された引数のみに依存する場合、関数は純粋であると言われます。したがって、関数が純粋な場合、引数に基づいて結果をキャッシュできます。この手法はメモ化と呼ばれます。これは、関数の計算にコストがかかり、複数回呼び出される場合に行います。

これを示すために使用される古典的な例 (ここなど) は、フィボナッチ数の生成です。それらがどのように解決されるかについては説明しませんが、基本的には、数値が高くなるにつれて、前の 2 つの数値から各数値が計算されるため、同じことを何度も繰り返すことになります。各中間結果をメモすることで、それらを 1 回だけ計算する必要があるため、アルゴリズムが大幅に高速化されます (シーケンスが上に行くほど高速になります)。

このコードに関する限り、メモライザーは 2 つのパラメーター (キャッシュである「メモ」) を取ります。この場合、'[0,1]' に既に入力されている最初の 2 つの値が入っています。これらは最初の 2 つのフィボナッチ数です。

2 番目のパラメーターは、メモ化が適用される関数です。この場合、再帰的なフィボナッチ関数:

function (shell, n) { return shell(n - 1) + shell(n - 2); }

つまり、結果はシーケンス内の前の 2 つの数値の合計です。

memoizer は最初に、既に結果がキャッシュされているかどうかを確認します。もしそうなら、それはすぐにそれを返します。そうでない場合は、結果を計算してキャッシュに保存します。これを行わないと、何度も何度も繰り返され、シーケンス内のより高い数値に達すると、信じられないほど遅くなります。

于 2010-09-26T17:59:22.350 に答える
1

関数を評価するには、次のように呼び出すだけです。

fibonacci(15);

結果を見たい場合、最も簡単な方法は次のとおりです。

alert(fibonacci(15));

これをもっと頻繁に行いたい場合は、Firebugをダウンロードし、スクリプトの最後でこれを行います。

Console.log(fibonacci(15));

または、これを Firebug コンソールに直接入力してから、Return キーを押します。

fibonacci(15)
于 2010-09-26T17:11:40.323 に答える