我正在寻找一个Clojure函数,让它调用它anyargs
,允许它的函数参数忽略多余的参数。所以,例如,
((anyargs cons) :a [:b :c] :d) ; => (:a :b :c)
如果函数参数采用了多个arities,那么选择最大拟合值是很好的。
答案 0 :(得分:4)
一种方法是检查函数以查看它需要多少个参数。 This link涵盖了检测此问题的方法。
如果稍微修改该答案,则会得到最大数量的参数:
(defn n-args [f]
(-> f class .getDeclaredMethods last .getParameterTypes alength))
这仅适用于方法数组按参数长度组织的情况,在我的系统中似乎是这种情况。如果你真的想确定,
(defn n-args [f]
(apply max
(map #(-> % .getParameterTypes alength)
(-> f class .getDeclaredMethods))))
然后你可以写:
(defn anyargs [f]
(let [n (n-args f)]
(fn [& args] (apply f (take n args)))))
这使用反射,并且它使用可变参数函数分解,但可能你不会将其用于可变参数函数。这是我现在能想到的最好的,除了提供一个捕获ArityExceptions的包装器,并继续用越来越少的参数重试,直到它工作。
答案 1 :(得分:1)
我认为你必须破解它。
(defn max-arities [f]
(reduce
#(merge-with max % {(.getName %2) (alength (.getParameterTypes %2))})
{}
(seq (.getDeclaredMethods (class +)))))
(defn anyargs [f]
(let [accept (if (instance? clojure.lang.RestFn f)
identity
(partial take ((max-arities f) "invoke")))]
(fn [& args] (apply f (accept args)))))
((anyargs cons) :a [:b :c] :d) ;=> (:a :b :c)
((anyargs +) 1 2 3 4 5 6 7 8 9 10) ;=> 55
答案 2 :(得分:1)
不干净,因为Clojure没有通过公共API公开其功能的arity。
鉴于您必须知道要应用的函数的arity,在特定情况下很容易实现这一点,其中n是arity
#(apply f (take n %&))