Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference among the functions doall dorun doseq and for?

Tags:

clojure

What is the difference between the functions doall, dorun, doseq, and for ?

I found some information scattered throughout the internet, but I think it would be better to centralize that information here.

like image 518
Carlos Nunes Avatar asked Aug 15 '14 13:08

Carlos Nunes


2 Answers

dorun, doall, and doseq are all for forcing lazy sequences, presumably to get side effects.

  • dorun - don't hold whole seq in memory while forcing, return nil
  • doall - hold whole seq in memory while forcing (i.e. all of it) and return the seq
  • doseq - same as dorun, but gives you chance to do something with each element as it's forced; returns nil

for is different in that it's a list comprehension, and isn't related to forcing effects. doseq and for have the same binding syntax, which may be a source of confusion, but doseq always returns nil, and for returns a lazy seq.

like image 172
overthink Avatar answered Oct 21 '22 14:10

overthink


You can see how dorun and doall relate to one another by looking at the (simplified) source code:

(defn dorun [coll]
  (when (seq coll) (recur (next coll))))

(defn doall [coll] (dorun coll) coll)
  • dorun runs through the sequence, forgetting it as it goes, ultimately returning nil.
  • doall returns its sequence argument, now realised by the dorun.

Similarly, we could implement doseq in terms of dorun and for:

(defmacro doseq [seq-exprs & body]
  `(dorun (for ~seq-exprs ~@body)))

For some reason, performance perhaps, this is not done. The standard doseq is written out in full, imitating for.

like image 43
Thumbnail Avatar answered Oct 21 '22 14:10

Thumbnail