Skip to content

Instantly share code, notes, and snippets.

@Chouser
Created August 24, 2016 14:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Chouser/b23f6acd1bd0f189fc32c408ad39cdbb to your computer and use it in GitHub Desktop.
Save Chouser/b23f6acd1bd0f189fc32c408ad39cdbb to your computer and use it in GitHub Desktop.
Argument counts from Clojure function objects
(require '[clojure.reflect :as r])
(defn arg-counts [f]
(let [mems (:members (r/reflect f))]
{:args (set (map #(count (:parameter-types %))
(filter #(= 'invoke (:name %)) mems)))
:varargs-ge (some #(when (= 'doInvoke (:name %))
(dec (count (:parameter-types %))))
mems)}))
(defn takes? [f n]
(let [{:keys [args varargs-ge]} (arg-counts f)]
(or (args n) (and varargs-ge (>= n varargs-ge)))))
(comment
user=> (takes? #() 0)
0
user=> (takes? #() 1)
nil
user=> (takes? #(+ % %2) 0)
nil
user=> (takes? #(+ % %2) 2)
2
user=> (arg-counts (fn ([]) ([a b c]) ([a b c d e f & xs])))
{:args #{0 3}, :varargs-ge 6}
user=> (takes? (fn ([]) ([a b c]) ([a b c d e f & xs])) 0)
0
user=> (takes? (fn ([]) ([a b c]) ([a b c d e f & xs])) 1)
false
user=> (takes? (fn ([]) ([a b c]) ([a b c d e f & xs])) 2)
false
user=> (takes? (fn ([]) ([a b c]) ([a b c d e f & xs])) 3)
3
user=> (takes? (fn ([]) ([a b c]) ([a b c d e f & xs])) 5)
false
user=> (takes? (fn ([]) ([a b c]) ([a b c d e f & xs])) 6)
true
user=> (takes? (fn ([]) ([a b c]) ([a b c d e f & xs])) 7)
true
user=> (takes? (fn ([]) ([a b c]) ([a b c d e f & xs])) 8)
true
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment