문제

Apologies if this is a newbie question... In Scala I understand that it is preferred to use an Option rather than returning null when you have a function which returns an instance but could potentially return nothing. I understand that this makes it better with regards to safety, because you are not passing null references around, and risking NullPointerException somewhere down the line.

However, is there a cleaner way to handle options than using pattern matching? The syntax I end up using is the following:

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

  case None => _
}

In reality all this doing is the equivalent of the Java version:

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

Is there some other way to avoid all this boilerplate in Scala when using Option instead of null references? All I want to do is execute a piece of code as long as the Option contains some object (i.e. is not None).

도움이 되었습니까?

해결책

Use foreach, getOrElse and/or map if you want to work in a more consistent way. Here's some use cases and what I'd do:

 //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

The third example will use map in both cases.

It gets really interesting when you can mix and match things in a "for comprehension" (Google term.) Let's say that func also returns an Option but I only want things working in specific cases:

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

Now I get back an Option but only if myOption contained an integer that was greater than zero. Pretty nifty stuff, no?

다른 팁

You can use foreach if you just want to perform some side-effecting operation with the value:

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

if you have some other use case you should use some other method on Option like map, filter or getOrElse.

Of course, the way I usually use options if I only care about present value is foreach:

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

Having said this, there are a lot of other options (which @wheaties enlisted) and some people keep battling about the true one.

You can use the flatMap-method pretty well with Option. Like 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

Here's a great reference for Scala best practices regarding options: http://blog.tmorris.net/posts/scalaoption-cheat-sheet/index.html

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top