Skip to content

Instantly share code, notes, and snippets.

@cgrand
Created August 26, 2015 04:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgrand/606fc40d2f04a6edf5b1 to your computer and use it in GitHub Desktop.
Save cgrand/606fc40d2f04a6edf5b1 to your computer and use it in GitHub Desktop.
xfor: transducing for
(defmacro xfor
"Like for except the first expression is omitted. Returns a transducer."
[[binding & seq-exprs] body]
(let [rf (gensym 'rf)
acc (gensym 'acc)
body
(reduce (fn [body [expr binding]]
(case binding
:let `(let ~expr ~body)
:when `(if ~expr ~body ~acc)
:while `(if ~expr ~body (reduced ~acc))
`(reduce (fn [~acc ~binding] ~body) ~acc ~expr)))
`(~rf ~acc ~body)
(partition 2 (rseq (vec seq-exprs))))]
`(fn [~rf]
(fn
([] (~rf))
([~acc] (~rf ~acc))
([~acc ~binding] ~body)))))
;; for vs xfor
(time (count (into []
(xfor [x
y (range 1e3)
:when (not= x y)]
(* x y))
(range 1e3))))
(time (count (into []
(for [x (range 1e3)
y (range 1e3)
:when (not= x y)]
(* x y)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment