Why does `vector` implementation have multiple cases?
Asked Answered
B

1

14

Here's clojure's definition of vector:

(defn vector
  "Creates a new vector containing the args."
  {:added "1.0"
   :static true}
  ([] [])
  ([a] [a])
  ([a b] [a b])
  ([a b c] [a b c])
  ([a b c d] [a b c d])
  ([a b c d & args]
     (. clojure.lang.LazilyPersistentVector (create (cons a (cons b (cons c (cons d args))))))))

Why are there so many cases? Or, if there are so many, why aren't there more?

My guess is that it's striking a balance between implementation efficiency and probability, but I don't quite see how this would be more efficient.

Bond answered 4/7, 2012 at 11:37 Comment(0)
H
22

4 seems to strike a balance of efficiency between when there are lots of arguments and when there are not many arguments.

As an example:

(defn vector-few
  ([] [])
  ([ & args ] (. clojure.lang.LazilyPersistentVector (create args))))


(defn vector-many
  ([] [])
  ([a] [a])
  ([a b] [a b])
  ([a b c] [a b c])
  ([a b c d] [a b c d])
  ([a b c d e] [a b c d e])
  ([a b c d e f] [a b c d e f])
  ([a b c d e f & args] (. clojure.lang.LazilyPersistentVector (create (cons a (cons b (cons c (cons d (cons e (cons f args))))))))))

Running a test with 4 elements:

=> (time (dotimes [x 1000000] (vector 1 2 3 4)))
"Elapsed time: 12.082104 msecs"

=> (time (dotimes [x 1000000] (vector-few 1 2 3 4)))
"Elapsed time: 443.056339 msecs"

=> (time (dotimes [x 1000000] (vector-many 1 2 3 4)))
"Elapsed time: 11.812106 msecs"

And then with 5:

=> (time (dotimes [x 1000000] (vector 1 2 3 4 5)))
"Elapsed time: 467.904979 msecs"

=> (time (dotimes [x 1000000] (vector-few 1 2 3 4 5)))
"Elapsed time: 537.080198 msecs"

=> (time (dotimes [x 1000000] (vector-many 1 2 3 4 5)))
"Elapsed time: 10.30695 msecs"

And with 8 (so all of the functions are using the var-args case):

=> (time (dotimes [x 1000000] (vector 1 2 3 4 5 6 7 8)))
"Elapsed time: 832.803266 msecs"

=> (time (dotimes [x 1000000] (vector-few 1 2 3 4 5 6 7 8)))
"Elapsed time: 689.526288 msecs"

=> (time (dotimes [x 1000000] (vector-many 1 2 3 4 5 6 7 8)))
"Elapsed time: 905.95839 msecs"
Hazing answered 4/7, 2012 at 12:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.