Fork me on GitHub
#clojure-dev
<
2018-01-26
>
ikitommi06:01:54

Would it be possible to have a function in the core to resolve function arities at runtime? Or is there such method already? It seems that can be done via reflection, but it’s really hacky.

ikitommi06:01:40

For example in Ring, there are handler/middleware with 1, 2 or 1 & 2 arities. Would be nice to be able to inspect ’em and fail fast instead of first invocation (to some particular path).

ikitommi06:01:57

With some googling, this seems to be the way to do it today:

(import '(java.lang.reflect Method))

(defn arities [f]
  (let [methods (-> f class .getDeclaredMethods)
        var-arg? (some #(-> ^Method % .getName (= "getRequiredArity")) methods)
        counts (->> methods
                    (filter #(= (.getName ^Method %) "invoke"))
                    (map #(.getParameterCount ^Method %))
                    (set))]
    (cond-> counts var-arg? (conj :*))))

(defn kikka ([_]) ([_ _]))

(doseq [f [kikka
           (fn kukka ([_ _]) ([_ _ _ _ _]) ([_ _ _ _ _ _ _ & _]))
           #()
           #(%5 %7)
           #(%)
           #(%&)]]
  (println (arities f)))
; #{1 2}
; #{:* 2 5}
; #{0}
; #{7}
; #{1}
; #{:*}

Alex Miller (Clojure team)13:01:33

Generally I find that when you get to the point where you are asking that question, probably you’re doing things you shouldn’t