OPのように、when-let
and if
、next
andlast
などを使用して再帰的なソリューションを構築しようとするとイライラします。そこで、@ ntalbsの回答を理解し、これをさらに進めることができるかどうかを確認しようとしています。 //clojuredocs.org/quickref/Clojure%20Core。
パート#1-オブザベーション:
cons
はリストの関数ですが、conj
はコレクションの総称関数でありconcat
、シーケンスの「Use(modification)」の下にリストされていますが、レイジーシーケンスを返します。では、これらのことは実際にはどのように異なりますか?
引数の順序が重要です。値とシーケンスは使用できませんconj
。シーケンスと値のみを使用できます。それcons
は逆です。concat
より寛容なようです。
user=> (type (conj 1 '(2 3 4 5)))
ClassCastException java.lang.Long cannot be cast to clojure.lang.IPersistentCollection clojure.core/conj (core.clj:83)
user=> (type (cons '(2 3 4 5) 1))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505)
3つの異なるリターンタイプ:Cons、PersistentList、またはLazySeq
user=> (type (cons 1 '(2 3 4 5)))
clojure.lang.Cons
user=> (type (conj '(2 3 4 5) 1))
clojure.lang.PersistentList
user=> (type (concat 1 '(2 3 4 5)))
clojure.lang.LazySeq
コレクションの種類ごとに異なる動作:
user=> (cons 3 (sorted-set 5 7 2 7))
(3 2 5 7) ; type = Cons, 3 is just appended to the list,
user=> (conj (sorted-set 5 7 2 7) 3)
#{2 3 5 7} ; type = PersistentTreeSet, with 3 in the correct position.
user=> (concat 3 (sorted-set 5 7 2 7)) ; LazySeq can't be directly returned, so...(order doesn't matter)
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505)
私の考えでconj
は、最も単純な動作をしているので、実際に怠惰なシーケンスまたは具体的にリストが必要な場合を除いて、これを優先的に使用します。
パート#2- @Ramyの「私には密度が高すぎる」@ntalbsのソリューションを理解する。
上記の説明conj
は、それがコレクションに物事を追加するための最も適切な方法であることを示唆しています。これはまさに@ntalbsのソリューションが行うことです。の使用法reduce
はhttp://clojuredocs.org/clojure_core/clojure.core/reduce にあります。これは、コレクション内の値をまとめながら関数を適用する効果的な方法です。
(reduce f val coll)
したがって、コレクションの各メンバーにreduce
適用されます。したがって、呼び出しはコレクションを取得し、最初に適用されます。次に、、、などを適用します。ここで、は前の手順の結果です。f
val
(reduce conj () coll)
(conj () (first coll))
(conj result (second coll))
(conj result (third coll))
result
reduce
非常に強力なコマンドのように見えます。
パート3-さらに別の解決策
(fn rev [coll]
(into () coll))
ドキュメントから、のinto
構文糖衣であるように見えます(reduce conj to-coll from-coll)
。これがエレガントなのか、それとも単に密集しているのかはわかりません。ただし、最小限のキーストロークで機能します。