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



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

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),我想让这个新规则适用于每个函数,而不必重写所有函数。是否有办法做到这一点,或者是否有一些很好的理由不可能/不习惯?

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

另外,map-indexed的第一个参数是数为2的函数,第二个参数是一个集合。

下面的函数返回你想要的(我猜)。

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

编辑

正如amalloy指出的那样,我误解了vector的使用。它不是作为数据的向量,而是作为函数

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

对于您定义的任何函数

都可以这样做
(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)))

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

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

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

  1. 它只对你自己写的函数有用,或者碰巧别人也用这种模式写的函数有用。
  2. 当涉及多重性时,它会引入歧义(即,如果f是2个或3个参数的函数,(f x y)是完整应用还是部分应用?)
  3. 它也不能真正处理变量性(你会遇到同样的模糊性问题)。

也许更好的方法是引入一个不同的函数来完成部分应用程序。例如:

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

当然,您可能希望选择一个比"partial-f"更好的名称。例如,对于map,您可以使用mapper。对于map-indexed,也许indexed-mapper是有意义的。

换能器(将)做的正是这个序列函数,在其他很酷的东西。

见:http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming

相关内容

最新更新