My colleagues and I are a bit stumped over the following code's behavior.
def a: String = {
None.foreach(return "1")
return "2"
}
def b: String = {
None.foreach(x => return "1")
return "2"
}
As expected, invoking b
does return "2". However, invoking a
returns "1". When exactly is return "1"
being evaluated when a
is executed?
All* function evaluations of the form
f({code})
are equivalent to
val temp = { code }
f(temp)
So, in the first case,
val temp = return "1"
None.foreach(temp) // Never reach this point!
While in the second,
val temp = (x: Nothing) => return 1
// Equivalent: new Function1[Nothing,String]{ def apply(x: Nothing) = return "1" }
None.foreach(temp) // Never call that weird function!
so everything is okay.
But, wait, foreach
takes an A => Unit
. How is return "1"
such a function? Well, Scala starts with the most specific type possible (Nothing
, which is a subclass of anything, and therefore promises to do anything you ask of it, except it can't exist). And, then, since no values is produced by the statement (control escapes via a return), it never modifies it from Nothing
. So, indeed, Nothing
is a subclass of Function1[A,Unit]
.
And to produce that Nothing
--well, to pretend to produce it--you actually run the code, and return.
* Actually, if the parameter is passed by name, it's secretly converted to () => { Code }
and passed in without evaluation.
The others have explained the behaviour, however it is best not to use return
at all.
I would write something like.
def b: String = {
None.map(x => "1").getOrElse("2")
}
Or if it was a List
I would use collectFirst
if I wanted to return the first item that matched something.
EDIT: I see the question is tagged as functional programming
. You should avoid return
if trying to program in a functional style. Take map which is A => B. If you use return
you voilate that type signature.
def a: String = {
val a = Option(5).map(x => if(x==6) return "aa" else 6); // isnt returning a `B` when x == 5.
a.toString
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With