1

私は Clojure を学ぼうとしているので、まず Euler の課題のプロジェクトに取り組むのが良い方法だと思いました。最初の課題は、3 または 5 で割り切れる 1000 未満の数をすべて合計することです。

私の元のコードは次のとおりです。

(defn div3 [input-no] (zero? (mod input-no 3)))
(defn div5 [input-no] (zero? (mod input-no 5)))
(reduce + (filter (or div3 div5) (range 1 1000)))

しかし、それは機能せず、フィルターは 5 で割り切れる数ではなく、3 で割り切れる数のリストを返すだけであることが判明しました。

コードを次のように変更しました。

(defn div3or5 [input-no] (or (div3 input-no) (div5 input-no)))
(reduce + (filter div3or5 (range 1 1000)))

正しい結果が得られましたが、元のコードが機能しなかった理由がわかりません。

誰かがこれに光を当てることができますか?

4

2 に答える 2

4

あなたが直面している問題filterは、述語 (入力を受け取り、true または false を返す関数) を最初の引数として期待することです。しかし、div3div5は関数であり、 と単純に組み合わせることはできませんordiv3引数を 1 つ取り、これをanddiv5呼び出しと両方の呼び出し、および両方の結果に供給する新しい関数を作成する必要がありますor

幸いなことに、これは Clojure で簡単に実行できます。

(filter #(or (div3 %) (div5 %)) (range1 1000))

#()関数をインラインで定義するための省略形 ( lambda%1とも呼ばれます) で、最初の引数に を使用して 2 番目の引数に取得できます%2。引数が 1 つしかない場合は、%for %1 see this questionを使用できます。

また、これは次のような形式#()の単なる構文糖衣であることも理解したい場合があります。いくつかの制限があります (たとえば、入れ子にすることはできません)。fn(fn [arg1 arg2 ... & restArgs] (forms))#()

于 2012-04-27T13:16:26.853 に答える
3

REPLで評価するだけ(or div3 div5)で、何が起こっているかを確認できます。

=> (or div3 div5)
#<user$div3 user$div3@73305c>

つまりor、関数に評価されますdiv3(それfilterを使用して、記述した動作を与えます)。

その理由は、 がor最初の非偽の引数 (つまり、nilorでない最初の引数false) を返すためです。この場合、引数は 2 つの関数オブジェクトであり、関数オブジェクトはnilまたはではありませんfalse

別の言い方をすればor、関数の結果ではなく、関数自体で起こっているということです。ポールが言ったように、無名関数を使用してor、関数自体ではなく結果に作用させることができます。

于 2012-04-27T13:21:37.077 に答える