简体   繁体   中英

Clean exception handling in Scala

In Ruby I often like to handle null values from collections with the following function:

def nilstuff(a,stuff="")
  if(a.nil?)
    return stuff
  else
    return a
  end
end

In Scala there is an annoyance that empty values in collections throw exceptions, not nil:

val myMap = Map[String, String]()
    myMap += ("Apple" -> "Plant")
    myMap += ("Walrus" -> "Animal")             
    println(myMap("Elephant"))
//Exception in thread "main" java.lang.ExceptionInInitializerError
//  at MyProgram.main(MyProgram.scala)
//Caused by: java.util.NoSuchElementException: key not found: Elephant

Is there a way to make a similar function in Scala that handles exceptions and returns the "stuff" instead?

println(missing_stuff(myMap("Elephant"),"Unknown"))

You can add a default value to your Map :

scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map

scala> val myMap = Map[String, String]().withDefaultValue("Unknown")
myMap: scala.collection.mutable.Map[String,String] = Map()

scala> myMap("foo")
res0: String = Unknown

Another option is the getOrElse method of Map .

Or apply a pattern match to the result of get :

myMap.get("foo") match {
  case Some(value) => useAsDesired(value)
  case None => useAsDesired("Unknown")
}

The last might be the most general solution to what your title calls "Clean exception handling."

There are several ways built in.

(1) Don't get the value, get an option.

myMap.get("Elephant")

Now that you have an Option , you can do all sorts of things with it (including get either its contents or a default value if there is none):

myMap.get("Elephant").getOrElse("")

(2) Get the value, or a default value if it's not there

myMap.getOrElse("Elephant", "")

(3) Create the map with a default value (warning--this will not survive filtering, mapping, or any other handy collections operations). Immutably you'd add this after you were done building the map:

val defaultMap = myMap.withDefault(_ => "")
defaultMap("Elephant")

With a mutable map, you might add it at the beginning:

val myMap = new collection.mutable.HashMap[String,String].withDefaultValue("")

(4) Add the item that you're missing when you find it not there (mutable maps only):

myMap.getOrElseUpdate("Elephant", "Dumbo")

Probably not what you want in this particular case, but often useful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM