Return to Scala

I am new to scala programmer and stumbled upon strange behavior.

def balanceMain(elem: List[Char]): Boolean = { if (elem.isEmpty) if (count == 0) true; else false; if (elem.head == '(') balanceMain(elem.tail, open, count + 1);.... 

Basically I want to return true if elem.isEmpty and count == 0 . Otherwise, I want to return false.

Now I read above that there is no need to add a return statement to scala. Therefore, I omitted return above. But it does not return a boolean value. If I add a return statement as return true . It works great. Why is this so?

Also, why it is believed that bad practice has return statements in scala

+48
scala return
Sep 24 '12 at 7:18
source share
5 answers

It is not as simple as omitting the return keyword. In Scala, if there is no return , then the return value is considered the last expression. So, if the last expression is what you want to return, you can omit the return keyword. But if what you want to return is not the last expression, then Scala will not know that you want to return it .

Example:

 def f() = { if (something) "A" else "B" } 

Here, the last expression of the function f is the if else expression, which evaluates to String. Since no explicit return specified, Scala will output that you want to return the result of this if / else: a String expression.

Now, if we add something after the if / else statement:

 def f() = { if (something) "A" else "B" if (somethingElse) 1 else 2 } 

Now the last expression is an if / else expression that evaluates to Int. So the return type of f will be Int. If we really wanted it to return String, then we had problems because Scala has no idea what we intended. Thus, we must fix this either by storing the String for the variable and returning it after the second if / else expression, or by changing the order so that the last is the last.

Finally, we can avoid the return keyword even with a nested if-else statement, such as yours:

 def f() = { if(somethingFirst) { if (something) // Last expression of `if` returns a String "A" else "B" } else { if (somethingElse) 1 else 2 "C" // Last expression of `else` returns a String } 

}

+84
Sep 24 '12 at 7:24
source share

This question is actually a bit more complicated as described in the answers so far. This Rob Norris blog explains this in more detail and gives examples where using return will actually break your code (or at least have non-obvious effects).

At this point, let me just quote the gist of the post. The most important statement at the very beginning. Print it like a poster and put it on the wall :-)

The return keyword is not "optional" or "inferrable"; it changes the meaning of your program, and you should never use it.

It gives one example where it really breaks something when you inline a function

 // Inline add and addR def sum(ns: Int*): Int = ns.foldLeft(0)((n, m) => n + m) // inlined add scala> sum(33, 42, 99) res2: Int = 174 // alright def sumR(ns: Int*): Int = ns.foldLeft(0)((n, m) => return n + m) // inlined addR scala> sumR(33, 42, 99) res3: Int = 33 // um. 

because

A return expression, when evaluated, discards the current calculation and returns to the caller of the method in which return appears.

This is just one example in a related post, and this is easiest to understand. There are more of them, and I urge you to go there, read and understand.

When you come from imperative languages ​​such as Java, at first it may seem strange, but as soon as you get used to this style, it will make sense. Let me close another quote:

If you find yourself in a situation where you think you want to return earlier, you need to think about how you determined your calculations.

+7
Aug 17 '16 at 10:12
source share

I do not program Scala, but I use a different language with implicit return (Ruby). You have the code after the if (elem.isEmpty) block - the last line of code is what was returned, so you are not getting what you expect.

EDIT: here's an easier way to write your function. Just use the boolean value isEmpty and count to automatically return true or false:

 def balanceMain(elem: List[Char]): Boolean = { elem.isEmpty && count == 0 } 
+3
Sep 24 '12 at 7:22
source share

By default, the last function statement is returned. In your example, another statement appears after the period, in which you want to get the return value. If you want to return something before your last statement, you still have to use return .

You can modify your example as follows to return Boolean from the first part

 def balanceMain(elem: List[Char]): Boolean = { if (elem.isEmpty) { // == is a Boolean resulting function as well, so your can write it this way count == 0 } else { // keep the rest in this block, the last value will be returned as well if (elem.head == "(") { balanceMain(elem.tail, open, count + 1) } // some more statements ... // just don't forget your Boolean in the end someBoolStatement } } 
+3
Sep 24 '12 at 7:29
source share

Do not write if without the corresponding else . When you add else to your snippet, you will see that your true and false are actually the last expressions of the function.

 def balanceMain(elem: List[Char]): Boolean = { if (elem.isEmpty) if (count == 0) true else false else if (elem.head == '(') balanceMain(elem.tail, open, count + 1) else.... 
+3
Sep 24 '12 at 18:35
source share



All Articles