Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
doseq that doesn't blow up with too much bytecode, and w/o (fn []) thunks
(defmacro doseqs
[seq-exprs & body]
(let [stk (gensym "stack__")
level (gensym "level__")
seq-exprs (partition 2 seq-exprs)
bindings (vec (map first seq-exprs))
init-exprs (vec (map second seq-exprs))
nbinds (count init-exprs)
symbol-binds (fn [n]
[(bindings n) `(nth ~stk ~(inc (* n 2)))])
emit-init (fn [n]
`(let [~@(mapcat symbol-binds (range n))]
~(init-exprs n)))]
;; going to create a stack of:
;; [seq0 bind0, seq1 bind1, seq2 bind2]
`(loop [~level 0 ~stk []]
(if (< ~level ~nbinds)
;; incomplete bindings
(let [sidx# (* 2 ~level)
previously-bound?# (< sidx# (count ~stk))
seq# (if-let [s# (and previously-bound?# (get ~stk sidx#))]
(next s#)
(seq (case ~level
~@(interleave (range nbinds)
(map emit-init (range nbinds))))))]
(if seq#
(let [~stk (if previously-bound?#
(pop (pop ~stk))
~stk)]
(recur (inc ~level)
(conj ~stk seq# (first seq#))))
(when (pos? ~level)
(recur (dec ~level) (pop (pop ~stk))))))
(let [~@(mapcat symbol-binds (range nbinds))]
~@body
(recur (dec ~level) ~stk))))))
(doseqs [x (range 5)
y (range 4)
z (range 3)
a (range 2)
b (range 3)
c (range 2)
d (range 2)
e (range 2)]
(println [x y z a b c d e]))
;; macroexpand
(loop [level__12802 0 stack__12801 []]
(if (< level__12802 8)
(let [sidx__10435__auto__ (* 2 level__12802)
previously-bound?__10436__auto__ (<
sidx__10435__auto__
(count stack__12801))
seq__10437__auto__ (if-let [s__10438__auto__
(and
previously-bound?__10436__auto__
(get
stack__12801
sidx__10435__auto__))]
(next s__10438__auto__)
(seq
(case
level__12802
0
(let [] (range 5))
1
(let
[x (nth stack__12801 1)]
(range 4))
2
(let
[x (nth stack__12801 1)
y (nth stack__12801 3)]
(range 3))
3
(let
[x (nth stack__12801 1)
y (nth stack__12801 3)
z (nth stack__12801 5)]
(range 2))
4
(let
[x (nth stack__12801 1)
y (nth stack__12801 3)
z (nth stack__12801 5)
a (nth stack__12801 7)]
(range 3))
5
(let
[x (nth stack__12801 1)
y (nth stack__12801 3)
z (nth stack__12801 5)
a (nth stack__12801 7)
b (nth stack__12801 9)]
(range 2))
6
(let
[x (nth stack__12801 1)
y (nth stack__12801 3)
z (nth stack__12801 5)
a (nth stack__12801 7)
b (nth stack__12801 9)
c (nth stack__12801 11)]
(range 2))
7
(let
[x (nth stack__12801 1)
y (nth stack__12801 3)
z (nth stack__12801 5)
a (nth stack__12801 7)
b (nth stack__12801 9)
c (nth stack__12801 11)
d (nth stack__12801 13)]
(range 2)))))]
(if seq__10437__auto__
(let [stack__12801 (if previously-bound?__10436__auto__
(pop (pop stack__12801))
stack__12801)]
(recur
(inc level__12802)
(conj
stack__12801
seq__10437__auto__
(first seq__10437__auto__))))
(when (pos? level__12802)
(recur (dec level__12802) (pop (pop stack__12801))))))
(let [x (nth stack__12801 1)
y (nth stack__12801 3)
z (nth stack__12801 5)
a (nth stack__12801 7)
b (nth stack__12801 9)
c (nth stack__12801 11)
d (nth stack__12801 13)
e (nth stack__12801 15)]
(println [x y z a b c d e])
(recur (dec level__12802) stack__12801))))
@ghadishayban

This comment has been minimized.

Copy link
Owner Author

commented Apr 24, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.