如何忽略不必要的论点?

时间:2012-08-02 11:57:48

标签: clojure

是否有简单的方法可以忽略不必要的参数?

例如: (#(+ %1 %2) 1 2)返回3

我想强制使用此代码

(#(+ %1 %2) 1 2 3)

也返回3。但它返回

  

java.lang.IllegalArgumentException:传递的args(3)数量错误   到。

如何更改#(+ %1 %2)

我希望有比#(+ (nth %& 0) (nth %& 1))更优雅的方式。

4 个答案:

答案 0 :(得分:18)

以下是我要使用的内容:

=> ((fn [a b & _] (+ a b)) 1 2 3)
=> 3

这会创建一个匿名函数,它接受任意数量的参数,但只添加前两个参数。 _符号没有做任何特别的事情,它只是惯用于“我不关心这件事,但我需要它以某种方式绑定”。如果你认为你将要做很多事情,那么你可能想要定义它:

(defn add-first-two
  [a b & _]
  (+ a b))

如果您真的使用#()语法,则必须在定义中的某处包含%&以“实现”它应该采用任意数量的参数。这并不意味着您必须在显示时将其编入索引,它只需要出现某处。这是一个例子:

=> (#(do %& (+ %1 %2)) 1 2 3)
=> 3

另一方面,这个解决方案涉及%&的某种处理,你不需要任何处理,可能稍微放慢速度(我不确定)这个,也许别人可以给我反馈意见)。一个相当有趣的解决方案是将%&粘贴到(comment ...)块中,该块将评估为nil

=> (#(do (comment %&) (+ %1 %2)) 1 2 3)
=> 3

更奇特的解决方案是使用#_...,这与(comment...)非常相似,只是读者实际将其从评估中删除,就好像你只是在那里输入任何东西一样。这样,也许我们可以将它粘贴在(+ ...)的主体内以缩短代码。

=> (#(+ %1 %2 #_%&) 1 2 3)
=> 3

你知道什么,它有效。我以前从未尝试过这个,我很惊讶它看起来有用。显然,在#_...部分被删除之前有一些处理。奇怪。

如果您不喜欢这些奇怪的评论解决方案,并且do没有为您执行此操作,您可以随时将其放在(if nil ...)块中:

=> (#(if nil %& (+ %1 %2)) 1 2 3)
=> 3

嗯,毕竟,我仍然最喜欢第一个解决方案(使用(fn ...)),但其中一些肯定是更短

答案 1 :(得分:5)

这适用于任意数量的参数,并且可读:

(fn [& args] (apply + args))

如果您只想使用前两个参数(根据Alex的评论):

(fn [& args] (apply + (take 2 args)))

您可以直接使用它:

((fn [& args] (apply + (take 2 args))) 1 2)
; => 3

或者将函数绑定到这样的符号:

(let [f (fn [& args] (apply + (take 2 args)))]
  (f 1 2))
; => 3

或创建一个var:

(def f (fn [& args] (apply + (take 2 args))))

或功能:

(defn f [& args] (apply + (take 2 args)))

最佳定义取决于您的使用案例。

答案 2 :(得分:4)

这是怎么回事?

(#(apply + (take 2 %&)) 1 2 3 4 5)
;; => 3

答案 3 :(得分:1)

user> (#(do %& (+ % %2)) 1 2)
3
user> (#(do %& (+ % %2)) 1 2 3)
3

它不是很优雅,但我认为这是可以接受的。