doseq与dorun结合之间是否有任何差异?

时间:2015-05-19 23:27:31

标签: clojure

我很清楚the difference between doseq and for,但两者似乎非常相似。事实上,在我看来doseq可以轻松地将for视为宏来实现。

(defmacro doseq' [bindings & body]
  `(dorun (for ~bindings ~@body)))

此实现与Clojure的doseq实现之间是否存在任何功能差异,或者它们实际上是否相同(以某种可能的性能差异为模)?

1 个答案:

答案 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宏的范围中逃脱。