Q:

When to use return statements in Scala?

I have some python code and I want to convert it to scala.
Python code:
def temp(x):
    if(x == 5):
        return "equal to 5" //basically, this would be a guard clause in a real world example
    // Maybe do some processing
    return "not equal to 5"

print(temp(5)) //prints "equal to 5"
print(temp(6)) //prints "not equal to 5"

I create a scala worksheet and try to translate it line by line but the result is not the same.
Scala code:
object test {
  def temp(x: Int): String = {
    if (x == 5)
      "equal to 5"
    "not equal to 5"
  }                                               //> temp: (x: Int)String

  temp(5)                                         //> res0: String = not equal to 5
  temp(6)                                         //> res1: String = not equal to 5
}

I removed the keyword return because I read that it is not required in scala, but apparently, I cannot remove it in this context. I get the correct result if I do not remove the keyword return.
Why cannot I remove it in this context? Is there some other way to use guard clauses in scala? Or is there something else that is causing the unexpected output?

A:

The key is to understand in Scala if-else expressions are just that - expressions, not control structures. Hence
if (x == 5) "equal to 5"

does not mean 
"if x equals five, then return five", 
instead it means something like
"if x equals five, then evaluate this expression to five, otherwise evaluate to uknown value."
In fact we could write
val v: Any = if (x == 5) "equal to 5"

Note how the type of v is Any, because we have not provided the else part of the expression, so the best compiler can do is deduce Any type. Providing else clause we have
val v: String = if (x == 5) "equal to 5" else "not equal to 5"

where we see v is now nicely typed to String as required. Now in Scala if we put an expression as the last expression in the block, then this becomes the return value of the function. Thus
def temp(x: Int): String = {
  if (x == 5)
    "equal to 5"
  "not equal to 5"
}  

is equivalent to
def temp(x: Int): String = {
  val v1: Any = if (x == 5) "equal to 5"
  // do nothing with v1

  val v2: String = "not equal to 5"
  return v2
}  

where we see temp will always return just v2. Instead we should write simply
def temp(x: Int): String =
  if (x == 5) "equal to 5" else "not equal to 5"

We could say if-else expression acts as a traditional control structure only when it is the last expression in the block.

More formally, in conditional expression if (1) 2 else 3

The type of the conditional expression is the weak least upper bound of the types of 2 and 3
if (1) 2 is evaluated as if it was if (1) 2 else ().

where () value has Unit type which is explained here.

