【问题标题】:Clojure doseq generates huge code?Clojure doseq 生成大量代码?
【发布时间】:2013-02-26 19:27:49
【问题描述】:

我最近一直在玩 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)))

然后:

(macroexpand q)

在我的机器上,这会产生大量代码(97331 字节)。这是正常的还是我做错了什么?运算符是一个简单的 defrecord。如果有人感兴趣,这里是扩展结果的链接:http://pastebin.com/6gw1q078

编辑:

通过同样的操作,但使用 for 形式,我得到的东西要小几个数量级(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)

结果在这里:http://pastebin.com/9MAKK3VD

为什么两者之间有如此巨大的差异? doseq 形式看起来很无辜,当我收到一个错误说 java class size has been exceeded 时,我真的很惊讶。

【问题讨论】:

    标签: macros clojure code-generation


    【解决方案1】:

    好吧,看看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))))))
    

    理想情况下,我们只需要最后一个let 表单,但doseq 会发出额外的代码来以特定方式处理chunked-seq,这样它就会获取第一个块,然后为块中的每个项目执行@ 的主体987654326@等。

    此代码是为 doseq 中的单个 seq 生成的,但是当您在其中包含第二个 seq 时,会生成类似的用于处理 chunked-seq 的代码,因此它的大小会爆炸。

    【讨论】:

    • 感谢您的解释,我在想它是这样的。它仍然感觉像一个很大的限制,我想知道这是预期的行为......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 2022-01-11
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 1970-01-01
    相关资源
    最近更新 更多