(defmacro doseq2 [seq-exprs & body] (let [forms (loop [[[binding seq-expr] & seq-exprs] (partition 2 seq-exprs) forms []] (if (and binding seq-expr) (let [[mods seq-exprs] (split-with (comp keyword? first) seq-exprs)] (recur seq-exprs (conj forms {:seq-expr seq-expr :mods mods :binding binding}))) forms)) emit-mod (fn [form [k expr]] (case k :while `(if ~expr (do ~form) (reduced nil)) :when `(when ~expr ~form) :let `(let ~expr ~form))) step (fn step [[e & exprs]] (let [inner-expr (if exprs (step exprs) `(do ~@body nil)) rfnbody (reduce emit-mod inner-expr (reverse (:mods e)))] `(reduce (fn [_# ~(:binding e)] ~rfnbody) nil ~(:seq-expr e))))] (step forms))) (def hund (into [] (range 100))) (def ten (into [] (range 10))) (def arr (int-array 100)) (def s "superduper") (println ";; big range, few bindings:") (println "core/doseq") (dotimes [_ 5] (time (doseq [a (range 100000000)]))) (println "doseq2") (dotimes [_ 5] (time (doseq2 [a (range 100000000)]))) (println ";; med range, few bindings:") (println "core/doseq") (dotimes [_ 5] (time (doseq [a (range 500000)]))) (println "doseq2") (dotimes [_ 5] (time (doseq2 [a (range 500000)]))) (println ";; small range, few bindings:") (println "core/doseq") (dotimes [_ 5] (time (doseq [a (range 500)]))) (println "doseq2") (dotimes [_ 5] (time (doseq2 [a (range 500)]))) (println ";; small unchunked reducible, few bindings:") (println "core/doseq") (dotimes [_ 5] (time (doseq [a s b s c s]))) (println "doseq2") (dotimes [_ 5] (time (doseq2 [a s b s c s]))) (println "core/doseq") (dotimes [_ 5] (time (doseq [a arr b arr c arr]))) (println "doseq2") (dotimes [_ 5] (time (doseq2 [a arr b arr c arr]))) (println ";; small chunked reducible, few bindings:") (println "core/doseq") (dotimes [_ 5] (time (doseq [a hund b hund c hund]))) (println "doseq2") (dotimes [_ 5] (time (doseq2 [a hund b hund c hund]))) (println ";; more bindings:") (println "core/doseq") (dotimes [_ 5] (time (doseq [a ten b ten c ten d ten ]))) (println "doseq2") (dotimes [_ 5] (time (doseq2 [a ten b ten c ten d ten ]))) (println "core/doseq") (dotimes [_ 5] (time (doseq [a ten b ten c ten d ten e ten]))) (println "doseq2") (dotimes [_ 5] (time (doseq2 [a ten b ten c ten d ten e ten])))