Reduce は問題なく動作しますが、左折に似ています。右に折りたたむことができる他の形式の reduce はありますか?
2 に答える
clojure 標準ライブラリが左折 (reduce) しか持たない理由は、実際には非常に微妙であり、右折の主な利点を得るほど clojure が怠惰ではないためです。
Haskell のような言語での右折の主な利点は、実際に短絡できることです。foldr (&&) True [False, True, True, True, True]
実際に評価されるようにすれば、非常に啓発的です。評価する必要があるのは、and
1 つの引数 (最初のFalse
) を持つ関数だけです。そこに到達すると、答えがわかり、 を評価する必要はありませんTrue
。
写真をよく見ると:
概念的には、右折はリストの最後から開始し、前方に移動しますが、実際には、リストの前方から評価を開始することがわかります。
これは、遅延/カリー化された関数と末尾再帰が clojure では得られないメリットをもたらす例です。
ボーナスセクション(興味のある方)
vemv からの推奨に基づいて、Clojure が遅延右折畳みを行うことができないというこの制限を回避するために、Clojure がコア名前空間に新しい関数を追加したことを言及したいと思います。reduced
Clojure の遅延を可能にするコア名前空間で呼び出される関数がありますreduce
。reduce
リストの残りを見ないように指示することで、ショートサーキットに使用できます。たとえば、数のリストを乗算したいが、リストにゼロが含まれることがあると疑う理由があり、ゼロに遭遇したらリストの残りを調べないという特殊なケースとして処理したい場合は、次のように記述できます。次のmultiply-all
関数 (reduced
最終的な答えが0
リストの残りの部分に関係なくあることを示すために を使用していることに注意してください)。
(defn multiply-all [coll]
(reduce
(fn [accumulator next-value]
(if (zero? next-value)
(reduced 0)
(* accumulator next-value)))
1
coll))
そして、それが短絡していることを証明するために、たまたまゼロを含む数の無限リストを乗算し、実際に次の答えで終了することを確認できます。0
(multiply-all
(cycle [1 2 3 4 0]))