2013-03-11 12 views
6

Recentemente ho giocato con Clojure e ho raggiunto un problema che non sono sicuro di come gestire. Ho una doseq con 7 parametri e si espande in un blocco enorme, quasi superando la dimensione massima della classe. Perché doseq si espande in un così enorme blocco di codice del clojure?Clojure doseq genera un codice enorme?

Esempio:

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

e poi:

(macroexpand q) 

sulla mia macchina questo dà un enorme pezzo di codice (97331 bytes). È normale o sto facendo qualcosa di sbagliato? L'operatore è un semplice defrecord. Ecco un link al risultato espansa se qualcuno è interessato: http://pastebin.com/6gw1q078

edit:

facendo lo stesso, ma con un per forma ottengo qualcosa di alcuni ordini di grandezza più piccolo (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) 

il risultato è qui: http://pastebin.com/9MAKK3VD

Perché c'è una grande differenza come tra i due? Il modulo doseq sembra abbastanza innocente, sono rimasto davvero sorpreso quando ho ricevuto un errore nel dire che la dimensione della classe java è stata superata.

risposta

3

Ebbene, guardando un piccolo macro-expasion del doseq rivela il motivo:

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

Idealmente abbiamo solo bisogno l'ultimo let forma, ma doseq emette un codice aggiuntivo per gestire chunked-seq in modo specifico tale da prende il primo pezzo e poi per ogni elemento nel blocco esegue il corpo di doseq e così via.

Questo codice viene generato per un singolo seq in doseq ma quando si ha il secondo seq in esso, viene generato un codice simile per la gestione di chunked-seq che quindi esplode di dimensioni.

+1

Grazie per la spiegazione, stavo pensando che fosse qualcosa del genere. Sembra ancora una grande limitazione e mi chiedo se questo è il comportamento previsto ... –

Problemi correlati