I've recently been playing with clojure and reached a problem that I'm not sure how to handle. I have a doseq with 7 parameters and it expands to a huge block, almost passing the maximum class size. Why does doseq expand to such a huge block of clojure code?
Example:
(def q '(doseq
[p0 (nth (:params operator) 0 (quote (nil)))
p1 (nth (:params operator) 1 (quote (nil)))
p2 (nth (:params operator) 2 (quote (nil)))
p3 (nth (:params operator) 3 (quote (nil)))
p4 (nth (:params operator) 4 (quote (nil)))
p5 (nth (:params operator) 5 (quote (nil)))
p6 (nth (:params operator) 6 (quote (nil)))]
(do-print board (:oname operator) p0 p1 p2 p3 p4 p5 p6)))
and then:
(macroexpand q)
on my machine this gives a huge chunk of code (97331 bytes). Is this normal or am I doing something wrong? Operator is a simple defrecord. Here's a link to the expanded result if anyone is interested: http://pastebin.com/6gw1q078
edit:
By doing the same, but with a for form I get something a few orders of magnitude smaller (3653 bytes):
(def q '(for
[p0 (nth (:params operator) 0 (quote (nil)))
p1 (nth (:params operator) 1 (quote (nil)))
p2 (nth (:params operator) 2 (quote (nil)))
p3 (nth (:params operator) 3 (quote (nil)))
p4 (nth (:params operator) 4 (quote (nil)))
p5 (nth (:params operator) 5 (quote (nil)))
p6 (nth (:params operator) 6 (quote (nil)))]
(do-print board (:oname operator) p0 p1 p2 p3 p4 p5 p6)))
(macroexpand q)
the result is here: http://pastebin.com/9MAKK3VD
Why is there such a huge difference between the two? The doseq form looks innocent enough, I was really surprised when I got an error saying that java class size has been exceeded.
Well, looking at a smaller macro-expasion of doseq
reveals the reason:
(loop [seq_2365 (seq [1 2])
chunk_2366 nil
count_2367 0
i_2368 0]
(if (< i_2368 count_2367)
(let [x (.nth chunk_2366 i_2368)]
(do x)
(recur seq_2365 chunk_2366 count_2367 (unchecked-inc i_2368)))
(when-let [seq_2365 (seq seq_2365)]
(if (chunked-seq? seq_2365)
(let [c__4197__auto__ (chunk-first seq_2365)]
(recur (chunk-rest seq_2365) c__4197__auto__ (int (count c__4197__auto__)) (int 0)))
(let [x (first seq_2365)]
(do x)
(recur (next seq_2365) nil 0 0))))))
Ideally we only need the last let
form but doseq
is emitting additional code to handle chunked-seq
in a specific way such that it takes the first chunk and then for each item in the chunk execute the body of doseq
and so on.
This code is generated for a single seq in doseq
but when you have 2nd seq in it then similar code for handling chunked-seq is generated and hence it explod in size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With