11

reduceを呼び出して関数と 2 つの引数を渡す場合、最初の引数はアキュムレータと見なすことができますか?

それは常にアキュムレータですか?

時々アキュムレータですか?

Clojure を使用して大きなファイルを解析することに関するブログ エントリを読んでいて、次の行を見つけました。

(reduce line-func line-acc (line-seq rdr))

ブログエントリへのリンク:

http://lethain.com/reading-file-in-clojure/

単純な(reduce + [1 2 3])はどうですか? アキュムレータが関係していますか?

「アキュムレータとは正確には何ですか?」

しかし、アキュムレータとreduce関数の関係も理解したいです。したがって、これらの特定の (関連する) 質問に対する回答は大歓迎です!

4

6 に答える 6

5

アキュムレータにすることができます。

それは、使用方法と、「アキュムレータ」の定義によって異なります。

以下は従来の変更可能なアキュムレータです。各ステップで同じアキュムレータを渡し続ける必要があることに注意してください。

(reduce 
  (fn [atom val] (do (swap! atom + val) atom))
  (atom 10)
  [1 2 3 4 5])
=> #<Atom@115872f5: 25>

これは、不変の「アキュムレータ」で使用されている reduce です。アキュムレータは伝統的に変更可能ですが、ほとんどの関数型プログラマーはこれをアキュムレータとして定義すると思います。

(reduce + 10 [1 2 3 4 5])
=> 25

これは、何も累積しない reduce です。そのため、2 番目の引数がアキュムレータであると主張するのは困難です。

(reduce 
  (fn [_ x] (println x))
  nil 
  [1 2 3])
于 2012-07-06T10:59:43.303 に答える
5

(reduce f val coll) で、val はアキュムレータですか?

いいえ、関数 f の引数です。これはf、val と coll の最初の要素に適用されることを意味します。

例えば:

(reduce + 1 [2 3 4])        ;; 10
(reduce + (cons 1 [2 3 4])) ;; 10

単純な (reduce + [1 2 3]) はどうですか? アキュムレータが関係していますか?

いいえ、機能の一連のアプリケーションとしてですf。このような:

(reduce f [1 2 3 4]) ; ==> (f (f (f 1 2) 3) 4)
(reduce f 1 [2 3 4]) ; ==> (f (f (f 1 2) 3) 4)

どちらの場合も、最も内側の への呼び出しfがパラメーター 1 と 2 を取ることに注意してください。最初のケースでは、1 と 2 が coll の 1 番目と 2 番目の要素です。2 番目のケースでは、1 が唯一の値で、2 が coll の最初の要素です。

アキュムレータとは正確には何ですか?

アキュムレータは、計算の中間結果を保持する変数です。Java のこのスニペットのように:

int sum = 0;
for (int i = 0; i < 10; i++) {
    sum += i;
}
return sum;

ここで、変数 sum の値は、ループが進行するにつれて変更されます。Clojure では、変数は不変であるため、このイディオムは表示されません。代わりに、アキュムレータは再帰関数へのパラメーターであることが多くなります (常にではありません)。

たとえば、リストの最初のエントリをアキュムレータの前に「蓄積」することで、リストを逆にする関数があります。この場合、変数は変更されませんが、関数の別の呼び出しに渡されます。

(defn reverse [[f & r] acc]
  (if (nil? f)
    acc
    (recur r (conj acc f))))

(reverse [1 2 3] ()) ;; [3 2 1]
于 2012-07-05T16:31:51.060 に答える
4

元の質問は、言語で使用される公式用語ではなく、一般的な用語としてアキュムレータを使用していると想定しています。

関数の後の最初の引数 (2 番目の引数) が Clojure の用語でアキュムレータと呼ばれるかどうかはわかりません。しかし、確かにそのように動作するようです。

以下では:

(defn reduce-csv-row
     "Accepts a csv-row (a vector) a list of columns to extract, 
     and reduces the csv-row to a smaller list based on selection
     using the values in col-nums (a vector of integer vector 
     positions.)"

    [csv-row col-nums]

    (reduce
        (fn [filter-csv-row col-num]

            ;Don't use vectors without the proper information in them.

            (if-not (<= (count csv-row) 1)
                (conj filter-csv-row (nth csv-row col-num nil))))
        []
        col-nums))

確かに、この関数を呼び出した後にシーケンスが返されることを期待しているので、アキュムレータは悪い用語ではないかもしれませんが、正式な用語としては言えません。

于 2012-07-05T16:33:07.313 に答える
2

それは常にアキュムレータですか?

はい、常にアキュムレータです。アキュムレータは、計算が進行するにつれて計算の中間値を保持するものであり、計算が終了すると、アキュムレータは計算の最終結果を持ちます。アキュムレータが可変であるか不変であるかは、アキュムレータの別の側面ですが、これがアキュムレータの概念です。

時々アキュムレータですか?

いいえ、それは常に a のアキュムレータです。AKAreduceの全体的な概念は、値のリストを単一の値に変換することであり、リスト内の次の要素の処理に処理の結果が必要な場合、そのような計算を行うためにアキュムレータが必要だからです。リストの前の要素など。reducefold

valアキュムレータの初期値 (関数シグネチャの一部) を渡さない場合、アキュムレータの初期値reduceはリストの最初の要素に設定され、リストの 2 番目の要素から処理が開始されます。

valを最初の引数として扱うことfは、概念的に正しくありません。この場合、最初に指定されfたものと常に同じものを取得する必要があるためです。これは、最初のパラメーターとしてvalの部分関数を作成するようなものです。への各呼び出しは、への呼び出しの以前の戻り値として取得されます。したがって、アキュムレータです。fvalfvalfval

于 2012-07-06T04:15:32.163 に答える
0

(reduce f x y)
  • x常にアキュムレータですか?いいえ。
  • x時々アキュムレータですか?いいえ

  • xに与えられる初期値reduceです。

アキュムレータとは正確には何ですか?

アキュムレータは、再帰関数の値として返されるローカル バインドです。

たとえば、reduce自分で実装する場合は、次のようにします。

(defn reduce [f acc coll]
  (if (empty? coll)
    acc
    (recur f (f acc (first coll)) (rest coll))))
  • accアキュムレータです: 引数であるため、ローカルです。
  • collが空の場合、関数の値として返されます。

何かがアキュムレータであるかどうかは、関数の本体に依存します。

たとえば、次のように実装するとreverse:

(defn reverse [coll]
  (loop [in coll, out ()]
    (if (seq in)
      (recur (rest in) (cons (first in) out))
      out)))

.. . 次にoutアキュムレータです。

しかし、このように実装すると:

(defn reverse [coll]
  (reduce conj () coll))

... アキュムレータはありません。

reduce呼び出し内でaccは、最初に にバインドされ()ます。()しかし、それがアキュムレータであると言っても意味がありません。

于 2014-09-05T07:48:52.550 に答える