(Clojure)创建一个部分函数而不是抛出一个参数太少的arity异常?

时间:2013-03-30 17:13:42

标签: syntax clojure

如果你给一个函数的参数太少,它会抱怨:

user=> (map-indexed vector)
ArityException Wrong number of args (1) passed to: core$map-indexed
clojure.lang.AFn.throwArity (AFn.java:437)

假设我想要做一些方便的事情,比如自动调用(partial map-indexed vector),我希望这个新规则适用于每个函数,而不必重写所有函数。有没有办法实现这一目标,还是有一些好的理由不可能/不是惯用的?

3 个答案:

答案 0 :(得分:2)

您已回答了自己的问题,partial是可行的方法。您应该更多地解释您的用例,以便给出更好的答案。

此外,map-indexed期望arity 2的函数作为第一个参数,而集合作为第二个参数。

以下内容返回一个能够执行您想要的功能(我猜)。

(defn foo [f] (fn [] (map-indexed f vector)))

修改

我误解了amalloy指出的vector的使用。它不是矢量数据,而是函数

除了如上所述使用fn和前面提到的partial之外,也许您可​​以创建一个单字符名称同义词(或一个非常简单的宏),它将扩展为一个调用到partial。如果您选择$,则为($ map-indexed vector)

答案 1 :(得分:1)

您可以为您定义的任何功能执行类似的操作

(defn f
  ;; The "real" f
  ([x y z] (whatever-f-does x y z))
  ;; Overloads to "automagically" construct partial applications
  ([x] (partial f x))
  ([x y] (partial f x y)))

当然,这可以用宏来抽象,但这就是模式。

我不知道这是不是一个好主意。这可能不是大多数Lispers对大多数函数所期望的,但我认为它在某些情况下可能非常有用。

这种方法也有一些限制。以下是我想到的一些内容:

  1. 它仅对您编写的函数有用,或者恰好由也使用该模式的其他人编写。
  2. 当涉及多个arity时引入歧义(即,如果f是2或3个参数的函数,是(f x y)f或部分应用的完整应用?)
  3. 它也无法真正处理变量arity(你遇到歧义问题)。
  4. 或许更好的方法是引入不同的功能来进行部分应用。例如:

    (defn partial-f [& args] (apply partial f args))
    

    当然,您可能希望选择比“partial-f”更好的名称。例如,对于map,您可以使用mapper。对于地图索引,也许索引映射器是有意义的。

答案 2 :(得分:1)

Transducers(will)会为序列函数执行此操作,以及其他很酷的事情。

请参阅:http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming