6

次のコードを見つけました (コイン チェンジャーのカタを解決するこのブログ投稿で):

(defn change-for [amount]
  (let [denominations [25 10 5 1]
        amounts (reductions #(rem %1 %2) amount denominations)
        coins (map #(int (/ %1 %2)) amounts denominations)]
    (mapcat #(take %1 (repeat %2)) coins denominations)))

私が難しいと思う部分は次のとおり(reductions #(rem %1 %2) amount denominations)です。

私が知ったように、削減は、特定の関数に基づいて、結果のコレクションを増分的に計算するだけです。例:(reductions + [1 2 3])を与え[1 3 6]ます。

1         ; first  element
1 + 2     ; second element
1 + 2 + 3 ; third  element

次の剰余を計算するrem関数は、非常に簡単に理解できます。

残りのコードを理解するために、次のことを試しました。

; first try, to see if this call works
; outside the original code (the change-for function)
(reductions #(rem %1 %2) 17 [10 5 1]) ; --> [17 7 2 0]

; tried to use the reductions which takes only one argument
; notice that 17 is now inside the array
(reductions #(rem %1 %2) [17 10 5 1]) ; --> [17 7 2 0]

; further simplified the expression
(reductions rem [17 10 5 1]) ; --> [17 7 2 0]

最後のステップは、このブログ投稿で説明されているように匿名関数を削除することでした。

ここで、(少なくとも私にとっては) 混乱します: rem2 つの引数を取り、 array を使用するときにそれらがどのように適用されるかわかりません[17 10 5 1]。私は次の呼び出しを試みました:

(rem [17 10 5 1]) ; --> gives error
(rem [17 10 5 1] [17 10 5 1]) ; --> also gives error
(rem 17 10) ; --> works, but how do you use it with collections?

remこの関数が関数でどのように機能するか、誰かが私に説明できますかreductions?

私がよく理解していないもう1つのことは、これらのパーセント引数はどのように適用されるの#(rem %1 %2)ですか? つまり、彼らはどこから来たのですか?次の方法で呼び出してみremましたが、エラーが発生します: (#(rem %1 %2) 17 [10 5 1]). reductionsこれを機能させるには、関数が舞台裏で何かをしているに違いありませんよね?

最初はセットかと思い#(rem %1 %2)ました。これらはセットと同様の方法で宣言され、簡単に誤用される可能性があります (Clojure を使い始めたばかりの人によって):

(type #{1 2 3})   ; --> clojure.lang.PersistentHashSet
(type #(1 2 3))   ; --> user$eval12687$fn__12688

「匿名関数の特別な形式」などのClojureのトリックを説明しているサイト/本/何かを教えてもらえますか? ほとんどのリソースは、Clojure の複雑さに立ち入ることなく、最も単純な構造 (他のすべての Lisp 派生物に似たもの) を提供するだけです。かなり見栄えの良いサイトを見つけました (また、上記の匿名関数についても説明しています)。他にそのようなリソースはありますか?

4

1 に答える 1

5

これ:

(reductions #(rem %1 %2) amount denominations)

これと同等です:

(reductions rem amount denominations)

そして気づいたように

(reductions function start collection) 

(リダクションの最初のステップの最初の引数として) collectionwithをリダクションした一連の中間結果を返します。2 つのパラメーターを取る必要があります。functionstartfunction

したがって、次の結果:

(reductions function start [1 2 3 4 5]) 

((function start 1) (function (function start 1) 2) ...) 

この構文は、2 つのパラメーター (および) を受け取り、それらを呼び出して結果を返す#(rem %1 %2)無名関数を定義するための省略形です。%1%2rem

それは以下と同等です:

(fn [a b] (rem a b))
于 2012-12-21T12:41:23.923 に答える