本文介绍了Clojure doseq生成巨大的代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近一直在玩clojure,并遇到一个问题,我不知道如何处理。我有一个doseq有7个参数,它扩展到一个巨大的块,几乎通过最大类的大小。为什么doseq扩展到这么大的clojure代码块?

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?

示例:

(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)))

然后:

(macroexpand q)

在我的机器上,这给出了一大块代码(97331字节)。这是正常还是我做错了什么?运算符是一个简单的defrecord。如果任何人感兴趣,可以点击以下链接查看扩展结果:

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

编辑:

通过执行相同操作,但使用 for 数量级小(3653字节):

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)

为什么两者之间有这么大的差别? doseq形式看起来没有问题,当我收到一个错误,说超过了java类大小时,我真的很惊讶。

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.

推荐答案

好了,看一下较小的 doseq 宏观消费的原因:

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))))))

理想情况下,我们只需要最后的 let doseq 正在发出额外的代码,以特定的方式处理 chunked-seq ,使得它占用第一个块,然后块中的每个项目执行 doseg 的正文。

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.

此代码是为 doseq 但是当你有第二个seq,那么类似的代码处理chunked-seq产生,因此它的大小爆炸。

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.

这篇关于Clojure doseq生成巨大的代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-13 19:18