2012-08-02 80 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