のClojureのfor
は怠惰なシーケンスを生成します。すべての再帰的なdfs
呼び出しの実際の評価は、関数の出力を出力する必要があるため、REPLによってのみトリガーされます(((()()) (())())
)。 (do (dfs graph :a) nil)
を評価すると、:a
が印刷されます。
ここで、Clojureの遅延配列は効率の点でevaluated in chunks of size 32です。したがって、REPL(str
関数を使用)が最初の要素レイジーシーケンスであるfor
(:b
を出力するはずです)を評価すると、そのseqの他の要素も評価され、子ノードのシーケンスが出力される前に:c
と:e
が出力されます。評価されています(これも怠惰です)。対照的に
、Clojurescriptの怠惰な配列は、戻り値が再帰的に文字列に変換されたときに、すべてが深さ優先順で評価され、(LazySeq does not implement IChunkedSeq)チャンクされず、一つ一つを評価します。
REPLのClojureとCLJSの両方で(first (for [i (range 300)] (do (println "printing:" i) i)))
を試してみると、CLJSには32個の数字が表示され、CLJSには32個の数字が表示されます。
評価の順序をより確実にする場合は、for
の代わりにdoseq
を使用するか、doall
にfor
を入れてください。
これが役に立ちます。
サイドノート:ちょうど@Joshとして、私はClojureの1.8で最後には:f
を取得していない、と括弧はcljs出力と同じです - ...それは本当に奇妙だ
私は、次の午前わかりません現在どのようにDFSの結果を使用したいのですか。副作用を使用する場合は、i。 e。それらが横断していることを確認するためにdoseq
を使用し、コンソールにすべてのノードを印刷:
(defn dfs-eager
([g v] (dfs-eager g v #{}))
([g v seen]
(println v)
(let [seen (conj seen v)]
(doseq [n (v g)]
(if-not (contains? seen n)
(dfs-eager g n seen))))))
これは、深さ優先、コンソールにすべてのノードを表示します。あなたは、戻り値としてトラバーサルを取得for
を使用しますが、あなたが実際に意味のある値を返すを確認するには: - あなたがしてトラバーサルを取得するために平らにすることができます
(defn dfs-lazy
([g v] (dfs-lazy g v #{}))
([g v seen]
(cons v
(let [seen (conj seen v)]
(for [n (v g)]
(if-not (contains? seen n)
(dfs-lazy g n seen)))))))
あなたは、ネストされたリスト(:a (:b (:d) (:f)) (:c (:g)) (:e))
を取得します。あなたはまた、怠惰の利益を得るでしょう。
clojure 1.8と1.9-alpha14の両方で、最後に ':f'がなく、私のparensはcljs parensと同じです。 – Josh
それは変です、私はClojure 1.8.0とClojureScript 1.9.229を使用しています。 – mac