我很清楚the difference between doseq
and for
,但两者似乎非常相似。事实上,在我看来doseq
可以轻松地将for
视为宏来实现。
(defmacro doseq' [bindings & body]
`(dorun (for ~bindings ~@body)))
此实现与Clojure的doseq
实现之间是否存在任何功能差异,或者它们实际上是否相同(以某种可能的性能差异为模)?
答案 0 :(得分:2)
从实际的角度来看for
返回一个惰性序列的事实意味着它不会在doseq所做的core.async中工作,因为它完全在同一个函数中运行。
user> (require '[clojure.core.async :refer [chan go <! <!! >!]])
使用doseq:
user> (let [stuff (chan)]
(go (while true
(println (<! stuff))))
(go (doseq [a (range 4)]
(>! stuff a))))
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x523a18bc "clojure.core.async.impl.channels.ManyToManyChannel@523a18bc"]
user> 0
1
2
3
使用for和dorun:
user> (let [stuff (chan)]
(go (while true
(println (<! stuff))))
(go (dorun (for [a (range 4)]
(>! stuff a)))))
CompilerException java.lang.IllegalArgumentException: No method in multimethod '-item-to-ssa' for dispatch value: :fn, compiling:(form-init5662188991458325584.clj:4:9)
失败,因为它试图在go块中跨越函数调用,因此从go宏的范围中逃脱。