2

IntelliJ's scalastyle get very upset at me when I write the following. It doesn't like that I wrote return.

def hasAnnotation(symbol: Symbol, annotation: Type): Boolean = {
  for (a <- symbol.annotations) {
    if ( a.tpe =:= annotation ) return true  // AVOID USING RETURN!!!
  }
  false
}

Why is adding return evil?

How can I shortcut iteration without return?

user48956
  • 14,850
  • 19
  • 93
  • 154
  • 1
    It would be nice if the answer clarified why `breakable` is supposedly evil. https://github.com/scala/scala/blob/v2.11.8/src/library/scala/collection/TraversableLike.scala#L130 in relation to https://github.com/scala/scala/blob/v2.11.8/src/library/scala/collection/TraversableOnce.scala#L90 – som-snytt Apr 26 '16 at 18:26
  • Is some disucssion here http://stackoverflow.com/questions/2742719/how-do-i-break-out-of-a-loop-in-scala – user48956 Apr 26 '16 at 19:05
  • Yes, as linked below, but doesn't make it plain to my simple mind. – som-snytt Apr 26 '16 at 19:13

2 Answers2

11

A more functional way of doing what you're requesting is

def hasAnnotation(symbol: Symbol, annotation: Type) = 
   symbol.annotations.exists(_.type =:= annotation)

This will short circuit upon finding the first item that satisfies the predicate. Return is not evil, it's just more imperative. Here's a link to another post talking about returning out of a loop

Community
  • 1
  • 1
nattyddubbs
  • 2,085
  • 15
  • 24
  • The linked answer makes breakable a sub-option. It ought to be either "blessed by stdlib" or shown to be harmful. – som-snytt Apr 26 '16 at 18:29
3

nattyddubbs has a nice implementation of your function without returns, but I can add a bit about why intellij is warning you about them.

Basically return works slightly differently in scala to what you might expect - the guys at jetbrains know that and have added a warning to make sure you really want a return there.

The problem is it returns the caller to the method in which the return appears... not the function. The best place to see this is in anonymous functions, for example imagine you have a function to sum a list

scala> def summer(as: List[Int]): Int = as.foldRight(0)((i,j) => i + j)

scala> summer(List(33, 42, 99))
res2: Int = 174

Cool. What happens if you use return?

scala> def summer(as: List[Int]): Int = as.foldRight(0)((i,j) => return i + j)

scala> summer(List(33, 42, 99))
res3: Int = 99

The meaning of the function has completely changed ... and you might not have expected it

OK you'd probably never write a return in a simple function like this, but you could easily do it in a more complex lambda and end up with results you don't expect

Rob Norris wrote a good blog post about return in scala here which is really worth reading

Hamish
  • 1,015
  • 9
  • 20