2

私はEloquentJavascriptを使用しています。関数countは、配列とテスト関数(equals(x))を引数として取り、テスト関数がtrueを返した配列内の要素の量を返します。

これらの関数が機能している幅広い方法を理解しています。論理的には、reduceに渡される無名関数への合計引数の値はゼロです。

誰かが私に合計の値が具体的にどこから来ているのかを知るのを手伝ってもらえますか?より明確なイメージを頭に入れたいと思います。

function count(test, array) {
  return reduce(function(total, element) { // Where is the value for total coming from?
    return total + (test(element) ? 1 : 0);
  }, 0, array);
}

function equals(x) {
  return function(element) {return x === element;};
}

function countZeroes(array) {
  return count(equals(0), array);
}

以前から機能を減らします:

function reduce(combine, base, array) {
  forEach(array, function (element) {
    base = combine(base, element);
  });
  return base;
}

以前のforEach関数:

function forEach(array, action) {
  for (var i = 0; i < array.length; i++)
    action(array[i]);
}
4

2 に答える 2

3

reduce には、結合関数ではなく無名関数が渡されていることがわかります

それは本当ではありません。無名関数combine関数です。

combine(base, element)function(total, element)

これら 2 つの関数呼び出しは本質的に互いに同等です: 結合 (ベース、要素) と関数 (合計、要素)?

いいえ、それらはまったく別のものです。

前者は、 によって参照される関数への関数呼び出しcombineです。
ただし、2 番目は新しい関数値に評価されます。の場合:

reduce(function(total, element) {...}, ...);

reduce()には関数値が渡されます。これが意味することは、新しい関数作成さtotalれるということです。これは、2 つのパラメーター (とで示されます) を受け入れる関数ですelement。この関数は に渡されreduceます。


昨日のビジュアライゼーションをリサイクルさせてください。これはあなたのケースだけに当てはまるのではなく、 reduce(left)コンセプトのすべての実施形態に当てはまることを認識することが重要です。

                   return value of reduce()
                   /
                 etc ...
                /
            combine    
           /       \
       combine      xs[2]
      /       \
  combine      xs[1]
 /       \
0         xs[0]

もちろん、これはが起こるかを示すだけであり、どのようにではなく、あなたの場合はどのように求めていると思います。この視覚化を念頭に置いて、結果がどうなるかを確認してください。

関数の代用

何が起こっているのかをより明確にするために、渡されている関数を徐々に置き換えます。

プログラムの開始:

function countZeroes(array) {
  return count(equals(0), array);
}

equals(0)(これを一種のカリー化と呼ぶことができます) は関数に評価され、 に渡されcount()ます。

これにより、基本的に次のcount()関数が得られます。

function count(array) {
  return reduce(function(total, element) { // Where is the value for total coming from?
    return total + (0 == element ? 1 : 0);
  }, 0, array);
}

ここから、combine引数を抽出できます。

function combine(total, element) { // Where is the value for total coming from?
    return total + (0 == element ? 1 : 0);
}

これは、reduce 関数内で使用される関数です。

function reduce(base = 0, array) {
  forEach(array, function (element) {
    base = combine(base, element);
  });
  return base;
}

reduce(0, array)関数から呼び出されcount()ます。に渡される関数はforEach、 の実装を考慮して、次のように書き直すことができますcombine

function reduce(base = 0, array) {
  forEach(array, function (element) {
    base = base + (0 == element ? 1 : 0);
  });
  return base;
}

baseを表すことに注意してくださいtotal

最後のステップとして、何をするかを考慮forEach()します。

function reduce(base = 0, array) {
  for (var i = 0; i < array.length; i++)
    base = base + (0 == array[i] ? 1 : 0);
  }
  return base;
}

したがって、これはcount()本質的に次のようになります。すべての呼び出しがラップされていません。

function count(array) {
  var base = 0;
  for (var i = 0; i < array.length; i++)
    base = base + (0 == array[i] ? 1 : 0);
  }
  return base;
}
于 2012-11-03T20:45:27.350 に答える
2

削減するために渡した3つの引数は次のとおりです。

{
    combine:function(total, element){...},
    base:0,
    array:array
}

次に、関数はそれを引数として関数baseに渡します。combinetotal

base = combine(base, element);

基本的に、ここで起こっていることは、(3番目の引数として)渡した配列の各要素に対して、関数が引数を取り、指定した無名関数(最初に要素が渡されるかどうかをチェックする)を使用してarray引数をインクリメントすることです。最後に、すべての要素を繰り返し処理した後、の最終値を返します。basetestbase

おそらくこれは説明に役立ちます:

function count(test, testarray) {
  var anon = function(total, element) { // Where is the value for total coming from?
    return total + (test(element) ? 1 : 0);
  };
  //now anon is a function.
  return reduce(anon, 0, testarray);
}

関数の呼び出しと定義を詳しく見てみましょう。

return   reduce(anon   , 0   , testarray);
                  |      |     |
                  v      v     v
function reduce(combine, base, array) {
    combine;    //the function that is passed in as the first argument
    base;       //the number that is passed in as the second argument
    array;      //the array that is passed in as the third argument

、、、およびのそれぞれのが関数に渡されます。関数内では、関数定義のパラメーター名からそれらの値にアクセスできます。anon0testarray

于 2012-11-03T20:07:33.817 に答える