2012-08-09 147 views
2

請考慮下面的例子在scala中傳遞默認參數?

def foo(a: Int, b: Int = 100) = a + b 
def bar(a: Int, b: Int = 100) = foo(a, b) * 2 

這工作,但要注意我必須提供相同的默認值,這兩種功能爲b。我的目的其實是下面

def bar(a: Int, b: Int) = foo(a, b) * 2 
def bar(a: Int) = foo(a) * 2 

但是,當你有更多的可選參數,而在鏈條的附加功能(如巴茲,在相同的方式調用吧)這個就變得很麻煩。有沒有更簡潔的方式來表達這個scala?

+2

請清楚地說出你的問題:你在這裏認爲什麼麻煩?你到底在找什麼?如果你正在尋找一種更簡潔的方式來編寫默認參數,那麼沒有,並且怎麼會有? – 2012-08-09 03:29:42

回答

3

我不認爲有;如果您撰寫foo且加倍功能:

val bar = (foo _).curried((_: Int)) andThen ((_: Int) *2) 
// (please, please let there be a simpler way to do this...) 

你失去了默認參數,因爲函數對象don't have them

如果它在你的用例中是值得的,你可以創建一個包含你傳遞的參數的case類,而不是多個單獨的參數。

case class Args(a: Int, b: Int = 100, c: Int = 42, d: Int = 69) 
def foo(args: Args) = { import args._; a + b + c + d } 
def bar(args: Args) = foo(args) * 2 
+0

完全真棒技術。每次遇到重載方法時,應由編譯器自己完成:將其轉換爲關聯的數據類和函數。對於操作,函數比方法更方便。 – ayvango 2012-08-09 12:17:31

+0

是的,我想案例分類解決方案是最好的。不過感覺這可能是一個有用的特性,可以在scala編譯器中輕鬆實現。我想到的是這樣的:def bar(a:Int,b:Int = _)= foo(a,b)* 2,scala可以檢查b僅用於定義了默認值的地方所以它可以毫不含糊地解釋這一點。 – user881423 2012-08-09 17:12:20

1

我建議使用Option

def bar(a: Int, b: Option[Int] = None) = b match { 
    case Some(x) => foo(a,x) * 2 
    case _ => foo(a) * 2 
} 

這將正是你想要的。另一種方法是使用可變參數。

def baz(a: Int)(b: Int*) = b.headOption match { 
    case Some(x) => foo(a,x) * 2 
    case _ => foo(a) * 2 
} 

我更喜歡第一種方式,因爲很明顯,參數是可選的。第二個解決方案並不是要處理Option中的包裝,但簽名並不清楚,只考慮集合的第一個元素。 baz(1)(2) == baz(1)(2,3,4,5)是真的。

編輯

爲了使一個與Option看起來像你期望的電話,您可以使用implicits。

implicit def int2Some(i: Int) = Some(i) 

現在,您可以撥打以下功能:

bar(1,2) 
bar(1,Some(2)) 
bar(1) 
bar(1,None) 

implicit被自動調用在以往任何時候它是有用的。但是您的用戶可能會感到困惑,爲什麼可以用Int而不是Option[Int]來調用該函數。

+0

第一個解決方案不允許你調用bar(1)。你必須說bar(1,None)。另外,以前的bar(1,2)現在需要寫成bar(1,Some(2))。使用重複的參數更接近所需的語法,但我想如果你有兩個或更多的可選參數,它不會工作?是的,它也有你提到的問題。 – user881423 2012-08-09 17:02:56

+0

您可以通過將其缺省設置爲無來解決第一個問題。我補充說。 – 2012-08-09 20:15:51

+0

第二個問題可能通過使用隱含來解決。我也加了一個。 – 2012-08-09 20:17:40