Get and fake the arity of any Clojure function




Get and fake the arity of any Clojure function.


[arity "0.2.0"]
(require 'arity.core)

API doc


;; Defined functions
(arities inc)                ;; => [1]
(arities +)                  ;; => [0 1 2 ##Inf]
(arities #'+)                ;; => [0 1 2 ##Inf]

;; Anonymous functions
(arities (fn []))            ;; => [0]
(arities (fn [a b & more]))  ;; => [##Inf]
(arities (fn ([a]) ([a b]))) ;; => [1 2]

;; #(...) anonymous functions
(arities #(apply + % %&))    ;; => [##Inf]
(arities #(+ %1 %2))         ;; => [2]

;; Macros
(arities #'->)               ;; => [##Inf]

Comes with min-arity and max-arity.


(def f (constantly 1))
(arities f)                    ;; => [##Inf]

(arities (fake-arities 1 f))     ;; => [1]
(arities (fake-arities [0 1] f)) ;; => [0 1] 

fake-arities is completely orthogonal to Clojure's native arity checks and its sole purpose is to force the return value of arities as well as min-arity and max-arity.

Why and when to use arity ?

Since Clojure heavely relies on destructuring, a function's arities often provide only a surface glance of the function's semantics, and any destructuring complex enough that it cannot be dealt with Clojure native DSL will have to be handled from within the obscurity of the function's insides. For instance:

(defn obscure-arity-fn [& args]
  (let [[a b c] (complex-destructuring args)]

This is why a function's arities cannot be used as a solid foundation in Clojure. However this plays nicely into enhancing a higher order function's understanding of its functionnal arguments, provided this function is directly exposed to the programmer using it rather than being used as the deeply buried crux of some subtle heuristic.

(defn configure [handler]
  (case (max-arity handler)
    1 (handler *context*)
    2 (do (println "Wow. Such mastery.")
          (handler *context* *debug-infos*))
    (throw (IllegalArgumentException. "Wrong handler arity"))))

Note that you will have to handle ambiguous variadic arities (##Inf). For instance the case statement in the example from above could be patched with :

(2 ##Inf) (do (println "Wow. Such mastery.")
              (handler *context* *debug-infos*))


Copyright © 2018 TristeFigure

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.