3

Here's the source code for update-in:

(defn update-in
 ([m [k & ks] f]
   (if ks
    (assoc m k (update-in (get m k) ks f))
    (assoc m k (f (get m k)))))
 ([m [k & ks] f a]
   (if ks
    (assoc m k (update-in (get m k) ks f a))
    (assoc m k (f (get m k) a))))
 ([m [k & ks] f a b]
   (if ks
    (assoc m k (update-in (get m k) ks f a b))
    (assoc m k (f (get m k) a b))))
 ([m [k & ks] f a b c]
   (if ks
    (assoc m k (update-in (get m k) ks f a b c))
    (assoc m k (f (get m k) a b c))))
 ([m [k & ks] f a b c & args]
   (if ks
    (assoc m k (apply update-in (get m k) ks f a b c args))
    (assoc m k (apply f (get m k) a b c args)))))

As far as I know (and I don't now much), this always gives the same result:

(defn my-update-in2
 ([m [k & ks ] f & args]
  (if ks
   (assoc m k (apply update-in (get m k) ks f args))
   (assoc m k (apply f (get m k) args)))))

My question: why isn't update-in (and many other Clojure functions) implemented this way? I would guess there are performance issues, ie. not using apply is faster.

nha
  • 17,623
  • 13
  • 87
  • 133

1 Answers1

6

Yes, you have guessed it correctly: some of the arities exist because of the performance cost of apply.

Having explicit arities for the most common cases (e.g. up to 3 arguments to the f function) improves performance as it translates to a direct function call.

Piotrek Bzdyl
  • 12,965
  • 1
  • 31
  • 49