2012-08-13 197 views
3

林想知道是否有一個簡短的手摺疊選項的地圖。例如斯卡拉,摺疊選項

def divideByThree(x:Int) = if (x == 0) None else Some(x/3) 

val result = Some(6) map (divideByThree(_)) 
resut:Option[Option[Int]] = Some(Some(2)) 

爲了解決這個問題我做

val result = Some(6) match { 
    case Some(i) => divideByThree(i) 
    case None => None 
} 

這似乎有點艱難的事。我可以在Option選項mapOption上創建一個隱式函數來處理這個問題,但是我想知道是否有更好的方法,我沒有想到。

def divideByThree(x:Int) = if (x == 0) None else Some(x/3) 

val opx = None // Or: Some(10) 
val mapped = opx.flatMap(divideByThree) 

println(mapped) 
+1

您是在用自己的方式[重新發現monads]​​(http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html)!除了提供一種嵌入值的方法(這裏是'Some')(以及在後者中),拆分嵌套結構/提供'flatMap' /'mapOption'-like函數的能力是構成monad的一半。情況下,一個'地圖'操作)。 – 2012-08-14 05:37:47

回答

9

您可以使用flatMap樣?它會執行map然後flatten

val result = Some(6) flatMap (divideByThree(_)) 
result: Option[Int] = Some(2) 
+0

一旦你看到它,它的各種明顯。 它總是一個很好的提醒,可以將Option作爲(至多)一個元素的列表。 乾杯! – 2012-08-13 11:20:19

2

如何flatMap()

1

Scala有一種一元語法:的理解

val div = (case x if x%3 == 0 => x/3} : PartialFunction[Int,Int]).lift 
val exp = (l : Option[Int]) => for { 
      x <- l 
      r <- div(x) 
      } yield r 

測試:

scala> exp(Some(3)) 
res1: Option[Int] = Some(1) 

scala> exp(Some(4)) 
res2: Option[Int] = None 

scala> exp(None) 
res3: Option[Int] = None