是否有一个适配器,使函数能够忽略多余的参数?

时间:2014-04-01 14:33:40

标签: clojure

我正在寻找一个Clojure函数,让它调用它anyargs,允许它的函数参数忽略多余的参数。所以,例如,

((anyargs cons) :a [:b :c] :d) ; => (:a :b :c)

如果函数参数采用了多个arities,那么选择最大拟合值是很好的。

3 个答案:

答案 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 %&))