Adr*_*san 6 macros code-generation clojure
我最近一直在玩clojure并遇到了一个我不确定如何处理的问题.我有一个带有7个参数的doseq,它扩展到一个巨大的块,几乎超过了最大的类大小.为什么doseq扩展到如此巨大的clojure代码块?
例:
(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)))
Run Code Online (Sandbox Code Playgroud)
然后:
(macroexpand q)
Run Code Online (Sandbox Code Playgroud)
在我的机器上,这提供了大量的代码(97331字节).这是正常的还是我做错了什么?运算符是一个简单的defrecord.如果有兴趣的话,这里是扩展结果的链接:http://pastebin.com/6gw1q078
编辑:
通过做同样的事情,但是使用for form,我得到的东西要小几个数量级(3653字节):
(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)
Run Code Online (Sandbox Code Playgroud)
结果如下:http://pastebin.com/9MAKK3VD
为什么两者之间存在如此巨大的差异?doseq表单看起来很无辜,当我收到错误说已经超出了java类的大小时,我真的很惊讶.
好吧,看看更小的宏观展开就能doseq揭示原因:
(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))))))
Run Code Online (Sandbox Code Playgroud)
理想情况下,我们只需要最后一种let形式,但会发出额外的代码以特定方式doseq处理,以便它获取第一个块,然后为块中的每个项目执行主体,依此类推。chunked-seqdoseq
该代码是为单个 seq 生成的doseq,但是当其中有第二个 seq 时,会生成用于处理 chunked-seq 的类似代码,因此它的大小会爆炸。