简体   繁体   中英

When to use keyword return in Scala

I learned early on that there is no reason to use the return keyword in Scala (as far as I'm aware). That being said I found an example where simply changing adding the return keyword made my function work, where it previously didn't.

The code in question comes from my solution to the Advent of Code day 7 challenge.


def containsShinyGoldBag(bagContents: Map[String, List[String]], currentBag: String): Boolean = {
    val contents = bagContents(currentBag)

    if (bagContents(currentBag).contains("shiny gold") ) {
        // Base Case: Bag Found in list of bags
        true
    } else if (contents == List.empty){
        // Base Case: Dead End
        false
    } else {
        // Continue searching down list

        // Ideal solution ( gives same result as the working solution without return keyword )
        // for (b <- contents) containsShinyGoldBag(bagContents, b)

        // Working solution
        for (b <- contents) {
            if (containsShinyGoldBag(bagContents, b)) {
                println(s"Found one! $b inside a $currentBag")
                return true // <--- culprit
            }
            else false
        }
        false
    }
}

// In the main function

var count = 0
for (bag <- bagContents.keys) {
    if (containsShinyGoldBag(bagContents, bag)) {
        count = count + 1
    }
}
println(s"There are $count way to bring a shiny gold bag!")

When I run the code without return I end up with count = 7 , which is the number of bags directly containing a shiny gold bag, rather than the correct number which counts bags that contain a shiny gold bag somewhere inside of one of their other bags down the line.

A function returns the value of the last expression it evaluates; in your case that will be one of:

  1. true after if (bagContents(currentBag).contains("shiny gold") ) ;

  2. false after else if (contents == List.empty) ;

  3. the last false .

true is not in such a position, so you need return to, well, make the function return it. Otherwise it's evaluated and ignored because you don't do anything with it. So is else false in the same for , actually, it can be removed without changing the meaning.

The alternative to avoid return here is

contents.exists(b => containsShinyGoldBag(bagContents, b))

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