2011-08-22 62 views
2
功能語法

有時我寫類似下面的代碼:嵌套IFS

val item1 = list.find(_.source.name.equals("foo")) 
if (item1.isDefined) doSomething1(item1) 
else { 
    val item2 = list.find(_.dest.name.equals("bar")) 
    if (item2.isDefined) doSomething2(item2) 
    else doSomethingElse() 
} 

沒有人有出來鋪設這段代碼一個更好的Scala語法?

+0

是doSomethings只是(邊)效果,或他們回報什麼意義? –

回答

6

我寫這篇文章的

list.find(_.source.name =="foo").fold(doSomething1) { 
    list.find(_.dest.name == "bar").fold(doSomething2)(doSomethingElse) 
} 

但那是因爲我已經添加的方法foldOption像這樣:

class FoldableOption[A](o: Option[A]) { 
    def fold[Z](f: A => Z)(g: => Z) = o.map(f).getOrElse(g) 
} 
implicit def option_has_folds[A](o: Option[A]) = new FoldableOption(o) 

如果你不想添加fold方法,您還可以使用map,getOrElse對:

list.find(_.source.name == "foo").map(doSomething1).getOrElse { 
    list.find(_.dest.name == "bar").map(doSomething2).getOrElse(doSomethingElse) 
} 

這不是更詳細。

+1

選項的摺疊方法也在[Scalaz庫]中實現(https://github.com/scalaz/scalaz/blob/6.0.1-for-2.8.x/core/src/main/scala/scalaz/OptionW .scala#L16)。 – CheatEx

2

與凱文說的一樣,如果這些表達式返回某些內容會更好。我會做同樣的事情,你但有不同的具體的例子:

val list = List(1,2,3,4) 
val result = list.find(_ == 1).map(
    _ => "Found1").orElse(list.find(_ == 5).map(
    _ => "Found2")).getOrElse("Found3") 

然而,你可能會更好看:)但避免副作用。鏈接,或單子鏈是一個表達式,而不是一些奇怪的副作用。

0

這應該工作,但它會稍微慢一些:

val item1 = list find (_.source.name == "foo") 
val item2 = list find (_.dest.name == "bar") 
item1 map (doSomething1) orElse { 
    item2 map (doSomething2) 
} getOrElse doSomethingElse() 

更新:更有效,但不是整齊:

val item1 = list find (_.source.name == "foo") 
item1 map (doSomething1) orElse { 
    val item2 = list find (_.dest.name == "bar") 
    item2 map (doSomething2) 
} getOrElse doSomethingElse() 
+0

這正是我所避免的(無論運行發現兩次)。 – schmmd