1

4Clojure サイトの問題 22を解決していて、シーケンス内の要素をカウントする関数を作成するよう求められています。ある時点で Haskell をいじったので、使用することfoldがおそらくそれを行うための方法であることを知っています。それについて読んだ後、私はreduce同じ目的で使用する必要があることを理解しました。私が提出した回答は次のとおりです。

#(reduce inc 0 %)

この背後にある理由は、リストを反復し、inc最初は 0 である値を毎回呼び出すことです。ただし、これは機能しません。サイトは、「間違った数の引数 (2) が渡されました: core$inc」と不平を言っています。だから私は括弧を追加しようとしましたinc:

#(reduce (inc) 0 %)

これで、 に引数が渡されていないと見なされincます。ここで何が間違っていますか?

4

5 に答える 5

10

そこで、incの周りに括弧を追加してみました...

コンパイラ/インタプリタをガイドする目的で、clojure で括弧を使用ないでください。clojure では、すべての括弧が重要であり、この方法では、引数なしで関数を呼び出すだけです。

次に、 reduce に関する clojure のドキュメントを見てください。

val が指定されている場合、f を val と coll の最初の項目に適用し、次にその結果と 2 番目の項目に f を適用した結果を返します。

だからあなたが書くとき

(reduce inc 0 [1 2 3])

実際に起こることは

(inc 
   (inc 
      (inc 0 1) 2) 3)

適切な機能は次のようになります

#(reduce 
    (fn [c _] (inc c))
     0 %)
于 2013-05-23T21:30:32.140 に答える
3

リストが

[1 2 3 4]

最初の例では、reduce にこれらを実行するように指示しています。

(inc 0 1)
(inc 0 2)
(inc 0 3)
(inc 0 4)

inc には、1 つ必要なときに 2 つの引数が渡されています。

2 回目の試行では、(inc) が値とリストで使用される関数を返すことを reduce に伝えています。(inc) は、引数なしの inc 関数の呼び出しです。

最初の引数を減らすために必要なのは、2 つの値を取り、最初の値を 1 増やして返す関数です。

于 2013-05-23T21:28:43.990 に答える
2

Clojure のreduceものは、haskell の left-fold function に似ていると考えることができますfoldl。リスト内の項目を数える Haskell の方法は次のxsようになります。

foldl (const . (+1)) 0 xs

これは としてよりよく理解されfoldl (\acc _ -> acc + 1) 0 xsます。

アイデアは、フォールド関数の最初のオペランドをインクリメントすることなので、次のように書きたくなります。

(reduce #(inc (%1)) 0 xs)

ただし、無名関数のアリティは式で参照される最高の引数によって決定され、 fold 関数のアリティは 2 でなければならないため、これは誤りです。

したがって、賢い回避策: (reduce #(inc (first %&)) 0 xs)

于 2016-10-22T07:46:59.710 に答える