使用带有清洁代码的选项

时间:2014-04-23 14:39:34

标签: scala scala-option

道歉,如果这是一个新手问题...... 在Scala中我理解当你有一个返回一个实例但可能没有返回任何内容的函数时,最好使用Option而不是返回null。我理解这在安全性方面做得更好,因为你没有传递空引用,并冒着NullPointerException在某处冒险。

但是,有没有比使用模式匹配更清晰的方法来处理选项? 我最终使用的语法如下:

val optObj : Option[MyObject] = myFunctionThatReturnsOption
optObj match {
  case Some(obj) => {
  //my code using obj
  }

  case None => _
}

实际上,这一切都等同于Java版本:

MyObject obj = myMethodThatCanReturnNull()
if (obj != null) {
  //my code using obj
}

使用Option而不是null引用时,是否有其他方法可以避免Scala中的所有样板?我想做的就是执行一段代码,只要Option包含一些对象(即不是None)。

5 个答案:

答案 0 :(得分:8)

如果您想以更一致的方式工作,请使用foreachgetOrElse和/或map。这是一些用例和我要做的事情:

 //I want to get a non-null value and I have a sane default
 val result = myOption getOrElse 3

 //I want to perform some side effecting action but only if not None
 myOption foreach{ value =>
   println(value toString ())
 }
 //equivalently
 for(value <- myOption){
   //notice I haven't used the "yeild" keyword here
 }

 //I want to do a computation and I don't mind if it comes back as an Option
 val result = for(value <- myOption) yield func(value)
 val equivalent = myOption map func

第二个例子在两种情况下都会使用map

当你能够在&#34;中理解混合和匹配时,它会变得非常有趣。 (Google术语。)让我们说func也会返回Option,但我只想在特定情况下工作:

 val result = for{ 
   value <- myOption if value > 0
   output <- func(value)
 } yield output

现在我回到Option,但前提是myOption包含一个大于零的整数。非常漂亮的东西,不是吗?

答案 1 :(得分:3)

如果您只想使用以下值执行某些副作用操作,则可以使用foreach

optObj.foreach(obj => {
    //my code using obj
})

如果您有其他一些使用案例,则应在Option上使用其他方法,例如mapfiltergetOrElse

答案 2 :(得分:1)

当然,如果我只关心现值,我通常使用选项的方式是foreach:

optObj.foreach { obj => 
 //...
}

话虽如此,还有很多其他的选择(@wheaties入伍),有些人一直在争论真正的选择。

答案 3 :(得分:1)

您可以使用flatMap - 方法很好地使用Option。跟hier一样:

case class Player(name: String)
def lookupPlayer(id: Int): Option[Player] = {
  if (id == 1) Some(new Player("Sean"))
  else if(id == 2) Some(new Player("Greg"))
  else None
}
def lookupScore(player: Player): Option[Int] = {
  if (player.name == "Sean") Some(1000000) else None
}

println(lookupPlayer(1).map(lookupScore))  // Some(Some(1000000))
println(lookupPlayer(2).map(lookupScore))  // Some(None)
println(lookupPlayer(3).map(lookupScore))  // None

println(lookupPlayer(1).flatMap(lookupScore))  // Some(1000000)
println(lookupPlayer(2).flatMap(lookupScore))  // None
println(lookupPlayer(3).flatMap(lookupScore))  // None

答案 4 :(得分:1)

以下是有关选项的Scala最佳实践的绝佳参考: http://blog.tmorris.net/posts/scalaoption-cheat-sheet/index.html