Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure和ClojureScript REPL产生不同的输出_Clojure_Clojurescript_Depth First Search_Read Eval Print Loop - Fatal编程技术网

Clojure和ClojureScript REPL产生不同的输出

Clojure和ClojureScript REPL产生不同的输出,clojure,clojurescript,depth-first-search,read-eval-print-loop,Clojure,Clojurescript,Depth First Search,Read Eval Print Loop,使用以下深度优先搜索的递归定义,Clojure(JVM)和ClojureScript(使用浏览器连接的repl和lumo进行测试)repl生成两种不同的输出,即打印节点的顺序不同,Clojure repl生成重复的:f。ClojureScript命令是我所期望的行为。为什么会这样 代码: Cloure REPL输出: :a :b :c :e :d :f :g :f ;; => ((() ()) (()) (())) :a :b :d :f :c :g :e ;; => ((() (

使用以下深度优先搜索的递归定义,Clojure(JVM)和ClojureScript(使用浏览器连接的repl和lumo进行测试)repl生成两种不同的输出,即打印节点的顺序不同,Clojure repl生成重复的
:f
。ClojureScript命令是我所期望的行为。为什么会这样

代码:

Cloure REPL输出:

:a
:b
:c
:e
:d
:f
:g
:f
;; => ((() ()) (()) (()))
:a
:b
:d
:f
:c
:g
:e
;; => ((() ()) (()) ())
CLojureScript REPL输出:

:a
:b
:c
:e
:d
:f
:g
:f
;; => ((() ()) (()) (()))
:a
:b
:d
:f
:c
:g
:e
;; => ((() ()) (()) ())

Clojure的
for
生成了一个惰性序列。所有重复的
dfs
调用的实际求值仅由REPL触发,因为它需要打印函数的输出,即
(())(())(())
。如果您计算
(do(dfs图:a)nil)
,则只会打印
:a

现在,Clojure的惰性序列是为了提高效率。因此,当REPL(通过
str
函数)计算第一个元素惰性序列时,顶层
(它应该打印
:b
),该序列的其他元素也会被计算,并且在计算子节点的序列(也是惰性的)之前打印
:c
:e

相比之下,Clojurescript的惰性序列不是分块的(LazySeq IChunkedSeq),而是一个接一个地进行计算,因此当返回值递归转换为字符串时,所有内容都按深度优先顺序进行计算

为了说明这一点,请在Clojure和CLJS中的REPL中尝试
(首先(对于[i(范围300)](do(println“printing:”i))
,您将在Clojure中打印32个数字,在CLJS中只打印一个数字

如果希望更好地保证求值顺序,可以使用
doseq
而不是
for
或将
for
包装在
doall

希望这有帮助

旁注:正如@Josh一样,我在Clojure 1.8中没有得到
:f
,并且paren与cljs输出相同-这真的很奇怪

我不确定我是否了解您当前希望如何使用DFS的结果。如果你想使用副作用,我。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
,我的参数与你的cljs参数相同。这很奇怪,我使用的是clojure 1.8.0和ClojureScript 1.9.229。谢谢你的回答。在我看来,评估顺序会受到分块的影响似乎很疯狂。另外,当我只打印
v
时,为什么其他元素会输出到REPL。如果我删除
println
调用,则不会打印任何内容。问题是您混合了副作用代码和惰性代码。在您的例子中,求值的顺序(以及事实本身)不仅取决于分块,而且还取决于您的REPL是否将函数
((())(())
的返回值输出到控制台——如果您仔细想想,这本身就是疯狂的。如果希望将结果输出到控制台,则可以使用命令式代码;如果希望将结果作为返回值,则可以使用函数式/惰性代码(请参阅上面“编辑到我的帖子”中的两个示例)。但混合使用这两种方法并不合适。