2013-03-11 16 views
6

Ostatnio grałem z clojure i doszłam do problemu, którego nie jestem pewien. Mam dawkę z 7 parametrami i rozszerza się do ogromnego bloku, prawie osiągając maksymalny rozmiar klasy. Dlaczego doseq rozszerza się na tak duży blok kodu clojure?Clojure doseq generuje ogromny kod?

Przykład:

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

, a następnie:

(macroexpand q) 

na moim komputerze to daje ogromny kawałek kodu (97331 bajtów). Czy to normalne, czy też robię coś nie tak? Operator to prosty defragment. Oto link do rozszerzonej rezultacie, jeśli ktoś jest zainteresowany: http://pastebin.com/6gw1q078

edit:

Robiąc to samo, ale z dla postaci otrzymuję coś kilka rzędów wielkości mniejszy (3653 bajtów):

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

wynik jest tutaj: http://pastebin.com/9MAKK3VD

Dlaczego jest taka duża różnica między tymi dwoma? Forma doseq wygląda niewinnie, byłem naprawdę zaskoczony, gdy dostałem komunikat o przekroczeniu rozmiaru klasy java.

Odpowiedz

3

Cóż, patrząc na mniejszą makro expasion z doseq ujawnia powód:

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

Idealnie musimy tylko ostatni let formę ale doseq emitującej dodatkowy kod do obsługi chunked-seq w specyficzny sposób taki, że pobiera pierwszą porcję, a następnie dla każdego elementu w kawałku wykonuje ciało doseq i tak dalej.

Ten kod jest generowany dla pojedynczego seq w doseq, ale gdy masz drugi seq, generowany jest podobny kod do obsługi chunked-seq, a więc eksploduje.

+1

Dzięki za wyjaśnienie, myślałem, że to coś w tym stylu. Nadal wydaje się dużym ograniczeniem i zastanawiam się, czy to zamierzone zachowanie ... –