Skip to content

Instantly share code, notes, and snippets.

@mecdemort
Created April 4, 2011 16:18
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save mecdemort/901895 to your computer and use it in GitHub Desktop.
(defmacro nested-for
"Like clojure.core/for but returns a nested structure for each sequence.
(for [x [:a :b] y (range 5) :when (odd? y)] [x y])
;=> (([:a 1] [:a 3]) ([:b 1] [:b 3]))"
[seqs body]
(let [groups (reduce (fn [groups [k v]]
(if (keyword? k)
(conj (pop groups) (into (peek groups) [k v]))
(conj groups [k v])))
[] (partition 2 seqs))]
(reduce (fn [res bindings]
`(for [~@bindings
:let [n# ~res]
:when (seq n#)]
(~transform n#)))
`(for ~(peek groups) ~body) (rseq (pop groups)))))
(nested-for [x (range 5)
:while (< x 3)
y (range 5)
:when (odd? y)]
[x y])
;=> (([0 1] [0 3]) ([1 1] [1 3]) ([2 1] [2 3]))
(macroexpand-1
'(nested-for [x (range 5)
:while (< x 3)
y (range 5)
:when (odd? y)]
[x y]))
(for [x (range 5)
:while (< x 3)
:let [n# (for [y (range 5)
:when (odd? y)]
[x y])]
:when (seq n#)]
n#)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment