Is there some reason to avoid return statements

2020-05-22 04:56发布

问题:

Sometimes I see chunks of Scala code, with several nested levels of conditionals and matchings, that would be much clearer using an explicit return to exit from the function.

Is there any benefit in avoiding those explicit return statements?

回答1:

A return may be implemented by throwing an exception, so it may have a certain overhead over the standard way of declaring the result of a method. (Thanks for Kim Stebel for pointing out this is not always, maybe not even often, the case.)

Also, a return on a closure will return from the method in which the closure is defined, and not simply from the closure itself. That makes it both useful for that, and useless for returning a result from closures.

An example of the above:

def find[T](seq: Seq[T], predicate: T => Boolean): Option[T] = {
  seq foreach { elem =>
    if (predicate(elem)) return Some(elem) // returns from find
  }
  None
}

If you still don't understand, elem => if (predicate(elem)) return Some(elem) is the method apply of an anonymous object of that implements Function1 and is passed to foreach as parameter. Remove return from it, and it won't work.



回答2:

One drawback is that the return type can't be inferred. Everything else is a matter of style. What seems unclear or confusing to you might be perfectly "natural" to someone else.



回答3:

An explicit return breaks the control flow. For example if you have a statement like

if(isAuth(user)) {
 return getProfile(user)
}
else {
 return None
}

the control structure (if) is not finished, which is the reason why I argue it is more confusing. For me this is analogous to a break statement. Additionally Scalas 'everything is a value' principle reduces the need for using explicit returns which leads to less people using a keyword which is only useful for def statements:

// start 
def someString:String = return "somestring"

// def without return 
def someString = "somestring"

// after refactoring
val someString = "somestring"    

You see that the type annotation has to be added and when changing the def to a val it is required to remove the return.