Making big bindings inside Clojure recursive function of bad performance?

I am writing a function that performs a set of transformations based on a declarative set of rules. Rules is a compilation with an estimate of compilation time (no function calls or anything else). They will contain hundreds of elements.

The main layout is as follows:

(defn dostuff-with-rules [stuff]
  (let [rules [["foo"] ["bar"] ["baz"] ...]
        transformed (reduce apply-rule stuff rules)]
    (if (not= stuff transformed)
      (recur transformed)
      transformed)))) 

I am concerned that initializing a large data set for each function call is detrimental to performance, and it is better to move it rulesout of scope.

Does that make sense or is Clojure smart enough to just initialize the rules once? Or maybe it makes sense to place loopinside the bindings let?

EDIT: , , , dostuff-with-rules node?

+4
1

Clojure (, , JVM) , , . /fn/recur, , .

, :

user> (time (loop [a 1]
              (if (< a 4)
                (let [big (vec (range 10e6))]
                  (do (println (rand-nth big))
                      (recur (inc a)))))))
9528975
717854
729682
"Elapsed time: 3753.978349 msecs"
nil

:

user> (def big (vec (range 10e6)))
#'user/big
user> (time (loop [a 1]
              (if (< a 4)
                (do (println (rand-nth big))
                    (recur (inc a))))))
4002962
7528467
2596236
"Elapsed time: 0.685522 msecs"
nil

, , , , , .

, ( )

user> (defmacro make-big-vec [] (vec (range 10000)))
#'user/make-big-vec
user> (time (loop [a 1]
              (if (< a 4)
                (let [big (make-big-vec)]
                  (do (println (rand-nth big))
                      (recur (inc a)))))))
CompilerException java.lang.RuntimeException: Method code too large!, compiling:(/tmp/form-init1716519094506420012.clj:1:7) 

1000 .

+5

All Articles