2013-03-11 7 views
6

Ich habe kürzlich mit Clojure gespielt und ein Problem erreicht, dass ich nicht sicher bin, wie ich damit umgehen soll. Ich habe eine doseq mit 7 Parametern und es erweitert sich zu einem riesigen Block, fast die maximale Klassengröße überschreiten. Warum erweitert sich doseq auf einen so großen Block von Clojure-Code?Clojure doseq erzeugt riesigen Code?

Beispiel:

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

und dann:

(macroexpand q) 

auf meinem Rechner gibt dies einen großen Teil des Codes (97.331 Bytes). Ist das normal oder mache ich etwas falsch? Operator ist ein einfacher Defrecord. Hier ist ein Link zu dem erweiterten Ergebnis, wenn jemand interessiert: http://pastebin.com/6gw1q078

edit:

Durch das gleiche zu tun, aber mit einem für Form ich etwas ein paar Größenordnungen kleiner (3653 Byte):

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

das Ergebnis hier: http://pastebin.com/9MAKK3VD

Warum gibt es einen so großen Unterschied zwischen den beide? Das doseq-Formular sieht unschuldig genug aus. Ich war wirklich überrascht, als ich einen Fehler erhielt, der besagt, dass die Java-Klassengröße überschritten wurde.

Antwort

3

Nun, bei einem kleineren Makro expasion von doseq suchen verrät den Grund:

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

Idealerweise brauchen wir nur die letzte let Form, sondern doseq wird zusätzlichen Code emittierende chunked-seq in einer bestimmten Art und Weise, so dass es zu handhaben nimmt den ersten Chunk und dann für jedes Element im Chunk den Körper von doseq und so weiter.

Dieser Code wird für einen einzelnen Seq in doseq erzeugt, aber wenn Sie 2. seq darin haben, dann wird ähnlicher Code für die Behandlung von chunked-seq erzeugt und folglich explodiert es in der Größe.

+1

Danke für die Erklärung, ich dachte, es ist etwas in dieser Richtung. Es fühlt sich immer noch wie eine große Einschränkung an und ich frage mich, ob das beabsichtigte Verhalten ist ... –