Getting values from a map

As I slowly progress in Scala I was trying to get values from a map and if not found return some kind of default value. Being still a java-head, I tried it initially to do it like the following:

var templates:Map[String, String] = Map()

... some code to fill the templates...

// wont compile
def locateTemplate(name: String) : String = {
    if (templates.get(name) == null) {
        templates.get(name)
    }
    else {
        // by default return the name itself
        name
    }
}


However this was too much java thinking. The compiler was complaining that I was not returning a String on the templates.get(name) line. But instead it returned an Option[String]. Hmm, not what I expected. Lets see with my java head. I have a map generified as strings, I insert key values as strings and yet, if I try to get the string for the key that must exist, then an option is returned? Time to look into the scala collections a bit more. And indeed, each object stored in a map is returned as either an Option[someObject] or None.

So having found that knowledge I decided to check for None value.

// wont compile either
def locateTemplate(name: String) : String = {
    if (templates.get(name) != None) {
        templates.get(name)
    }
    else {
        // by default return the name itself
        name
    }
}

Duh, same error of course, still trying to return an Option instead of a String. Luckily, each option object has the get method which will return the wrapped object, soooo

def locateTemplate(name: String) : String = {
    if (templates.get(name) != None) {
        templates.get(name).get
    }
    else {
        // by default return the name itself
        name
    }
}

But this seemed a bit too much java like and I thought that it could be done in a more functional scala way, right? And indeed it can. Each map also has the option (pun intended) to return the found wrapped object or return something else if not found. The final code will then look like:

def locateTemplate(name: String) : String = {
    templates.getOrElse(name, name) 
    // where the second name is the default value
}

Well that looks much better. And since its now a single statement, let’s get rid of the { } and the equal sign as well.

def locateTemplate(name: String) : String = templates.getOrElse(name, name)

And thats all there is left of the locateTemplate. Looks a lot smaller than the java I started with.