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)))
을 시도해보십시오. 클로저에는 32 개의 숫자가 인쇄되고 CLJS에는 하나의 번호 만 인쇄됩니다.
평가 순서를 더 잘 보장하려면 for
대신 doseq
을 사용하거나 doall
에 for
을 입력하십시오.
희망이 도움이됩니다.
사이드 참고 : 단지 @Josh로, 나는 Clojure의 1.8에서 결국에는 :f
를 얻을 수없고, 괄호는 cljs 출력과 동일하다 - ... 그건 정말 이상 하네
난 다음입니다 확실하지 않다 현재 DFS의 결과를 사용하는 방법. 부작용을 사용하고 싶다면, i. 이자형. 그들이 통과되어 있는지 확인 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