2012-08-02 78 views
10

有没有简单的方法可以忽略不必要的参数?如何忽略不必要的参数?

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

我想迫使该代码

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

来回报3了。但它返回

java.lang.IllegalArgumentException:错误的参数数目(3)传递给 。

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

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

回答

18

这里就是我会去:

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

这将创建一个匿名函数,它接受任何数量的参数,只是增加了第2位。 _符号没有做任何特殊的事情,它只是“我不在乎这件事,但我需要它以某种方式绑定”的习惯用法。如果你认为你会这是做了很多,那么你可能要定义它:

(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 ...)),但其中一些肯定是更短

5

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

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

如果你只是想用第2个参数(按照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 

或者创建一个变种:

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

或函数:

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

最好的定义取决于你的使用情况。

+2

这是总结所有的参数。 OP要求前两项的总和,忽略任何附加项,所以你必须说(fn [&args](apply +(take 2 args))) – Alex 2012-08-02 15:12:24

+1

这是一个很好的观点 - 更新了我的答案。 – Gert 2012-08-02 21:51:01

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

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

4

这个怎么样?

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