如何确定一个函数的参数数量在Clojure? [英] How can I determine number of arguments to a function in Clojure?

查看:104
本文介绍了如何确定一个函数的参数数量在Clojure?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在clojure中给出一个函数x如何以编程方式获取参数个数?

Given a function x in clojure how can I programatically get a count of the number of arguments?

例如:

(fn a [b c] ...) has has two arguments
(fn a [] ...) has has zero arguments


推荐答案

如果你可以访问保存函数的var,通过以下列方式访问其元数据:

If you have access to the var that holds the function you can get the argument count by accessing its metadata in the following way:

(defn arities [v]
  (->> v meta :arglists (map count)))

(defn a [])
(defn b [_ _])

(map arities [#'a #'b])
;= ((0) (2))

arities 将返回一个seq和所有的函数的arity。这具有缺点,对于可变参数向量( [_ _& _] ),它将返回(4)。

arities will return a seq with all the arities for the function. This has the disadvantage that for a variadic argument vector ([_ _ & _]) it will return (4).

(defn c [_ _ & _])
(arities #'c)
;= (4)

这可以通过从所有参数列表中删除&

This could be fixed by removing the & symbol from all the argument lists.

(defn arities [v]
  (->> v 
    meta 
    :arglists 
    (map #(remove #{'&} %))
    (map count)))

(arities #'c)
;= (3)



如果你没有访问var,下面是一个小功能我已经用来检测函数的参数计数。它使用反射,所以它不是你可能想要采取的,如果你需要良好的性能。还要考虑它依赖于实现的细节。

If you don't have access to the var, the following is a little function that I've used to detect the argument count of a function. It uses reflection so it's not the approach you might want to take if you need good performance. Also take into account that it relies on implementation details.

(defn n-args [f]
  (-> f class .getDeclaredMethods first .getParameterTypes alength))

(defn a [])
(defn b [_ _])
(defn c [_ _ & _])

(map n-args [a b c])
;= (0 2 3)






EDIT

我意识到结果3的变量函数定义为(defn x [_ _& _] ,,,),实际上是相当误导,因为它是相同的结果,你会获取具有3个参数的函数。以下版本将为包含& 符号的参数向量返回:variadic (除了 [&] 其中& 这是实际的参数名称)。如在 Jeremy Heiler 的注释中所提到的,从元数据获取参数计数只有在:arglists 的值未手动更改时才有效。 p>

After giving the answer another read, I realized the result 3 for a variadic function defined as (defn x [_ _ & _] ,,,), is actually quite misleading since it's the same result you would get for a function with 3 arguments. The following version will return :variadic, instead of a specific number, for the argument vectors that contain the & symbol (except for the case [&] where & it's the actual argument name). As mentioned in a comment by Jeremy Heiler getting the argument count from the metadata only works if the value for :arglists is not manually changed.

(defn a [_])
(defn b [_ _])
(defn c [_ _ & _])
(defn d [_ _ _])
(defn e [&])

(defn variadic? [s]
  (and (some #{'&} s)
       (not (every? #{'&} s))))

(defn arities [v]
  (->> v
    meta
    :arglists
    (map #(if (variadic? %) :variadic %))
    (map #(if (sequential? %) (count %) %))))

(map arities [#'a #'b #'c #'d #'e])
;= ((1) (2) (:variadic) (3) (:variadic))

更复杂,它依赖于更多的实现细节(即这是或那个函数声明吗?或函数是否扩展类X?),所以我不建议使用该方法。

The reflection version for this is a little more complicated and it relies on more implementation details (i.e. "Is this or that function declared?" or "Does the function extend the class X?"), so I wouldn't recommend using that approach.

这篇关于如何确定一个函数的参数数量在Clojure?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆