Created
April 24, 2016 05:19
-
-
Save ghadishayban/fe84eb8db78f23be68e20addf467c4d4 to your computer and use it in GitHub Desktop.
doseq that doesn't blow up with too much bytecode, and w/o (fn []) thunks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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)))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://dev.clojure.org/jira/browse/CLJ-1322