2012-08-13 133 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