Gab*_*iMe 47 functional-programming clojure
给定一个函数对象或名称,我该如何确定它的arity?有点像(arity func-name).
我希望有一种方法,因为arity在Clojure中非常重要
Mik*_*las 51
函数的arity存储在var的元数据中.
(:arglists (meta #'str))
;([] [x] [x & ys])
Run Code Online (Sandbox Code Playgroud)
这要求使用defn或:arglists明确提供的元数据定义函数.
小智 50
偷偷摸摸的反思:
(defn arg-count [f]
(let [m (first (.getDeclaredMethods (class f)))
p (.getParameterTypes m)]
(alength p)))
Run Code Online (Sandbox Code Playgroud)
要么 :
(defn arg-count [f]
{:pre [(instance? clojure.lang.AFunction f)]}
(-> f class .getDeclaredMethods first .getParameterTypes alength))
Run Code Online (Sandbox Code Playgroud)
小智 6
我的心在流血(涵盖所有情况)。
\n\n(defn arity\n "Returns the maximum arity of:\n - anonymous functions like `#()` and `(fn [])`.\n - defined functions like `map` or `+`.\n - macros, by passing a var like `#\'->`.\n\n Returns `:variadic` if the function/macro is variadic."\n [f]\n (let [func (if (var? f) @f f)\n methods (->> func class .getDeclaredMethods\n (map #(vector (.getName %)\n (count (.getParameterTypes %)))))\n var-args? (some #(-> % first #{"getRequiredArity"})\n methods)]\n (if var-args?\n :variadic\n (let [max-arity (->> methods\n (filter (comp #{"invoke"} first))\n (sort-by second)\n last\n second)]\n (if (and (var? f) (-> f meta :macro))\n (- max-arity 2) ;; substract implicit &form and &env arguments\n max-arity)))))\n\n(use \'clojure.test)\n\n(defmacro m ([a]) ([a b]))\n(defmacro mx [])\n\n(deftest test-arity\n (testing "with an anonymous #(\xe2\x80\xa6 %1) function"\n (is (= 1 (arity #(+ % 32))))\n (is (= 1 (arity #(+ %1 32))))\n (is (= 2 (arity #(+ %1 %2))))\n (is (= 13 (arity #(+ %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13))))\n (is (= :variadic (arity #(apply + %&))))\n (is (= :variadic (arity #(apply + % %&)))))\n (testing "with an anonymous (fn [] \xe2\x80\xa6) function"\n (testing "single body"\n (is (= 0 (arity (fn []))))\n (is (= 1 (arity (fn [a]))))\n (is (= 2 (arity (fn [a b]))))\n (is (= 20 (arity (fn [a b c d e f g h i j k l m n o p q r s t]))))\n (is (= :variadic (arity (fn [a b & more])))))\n (testing "multiple bodies"\n (is (= 0 (arity (fn ([])))))\n (is (= 1 (arity (fn ([a])))))\n (is (= 2 (arity (fn ([a]) ([a b])))))\n (is (= :variadic (arity (fn ([a]) ([a b & c])))))))\n (testing "with a defined function"\n (is (= :variadic (arity map)))\n (is (= :variadic (arity +)))\n (is (= 1 (arity inc))))\n (testing "with a var to a macro"\n (is (= :variadic (arity #\'->)))\n (is (= 2 (arity #\'m)))\n (is (= 0 (arity #\'mx)))))\n\n(run-tests)\nRun Code Online (Sandbox Code Playgroud)\n
基于@whocaresanyway 的解决方案:
(defn provided
[cond fun x]
(if cond
(fun x)
x))
(defn append
[xs x]
(conj (vec xs) x))
(defn arity-of-method
[method]
(->> method .getParameterTypes alength))
(defn arities
[fun]
(let [all-declared-methods (.getDeclaredMethods (class fun))
methods-named (fn [name]
(filter #(= (.getName %) name) all-declared-methods))
methods-named-invoke (methods-named "invoke")
methods-named-do-invoke (methods-named "doInvoke")
is-rest-fn (seq methods-named-do-invoke)]
(->> methods-named-invoke
(map arity-of-method)
sort
(provided is-rest-fn
(fn [v] (append v :rest))))))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6455 次 |
| 最近记录: |