Returns the second line if empty at first?

Here is the idiom I find myself.

def chooseName(nameFinder: NameFinder) = {
  if(nameFinder.getReliableName.isEmpty) nameFinder.getReliableName
  else nameFinder.secondBestChoice
}

      

To avoid having to be called getReliableName()

twice on nameFinder

, I add code that makes my method less elegant.

def chooseName(nameFinder: NameFinder) = {
  val reliableName = nameFinder.getReliableName()
  val secondBestChoice = nameFinder.getSecondBestChoice()
  if(reliableName.isEmpty) reliableName
  else secondBestChoice
}

      

This seems messy because I am creating unnecessary amount of state with help vals

for no reason other than to prevent the method from being called again. Scala taught me that whenever I feel dirty, there is almost always a better way.

Is there a more elegant way to write this?

Here two Strings, return whichever isn't empty while favoring the first

      

+3


source to share


5 answers


There is no need to always call getSecondBestChoice

, of course. Personally, I don't find anything illogical in the code after changing it - it is clear what it does, it has no mutable state. The other answers just seem tricky to avoid usingval

def chooseName(nameFinder: NameFinder) = {
  val reliableName = nameFinder.getReliableName()

  if(reliableName.isEmpty) reliableName
  else nameFinder.getSecondBestChoice()
}

      

If you really want to avoid val, here's another option (generalizes well if there are more than two alternatives)



List(nameFinder.getReliableName(), nameFinder.getSecondBestChoice()).find(_.nonEmpty).get

      

(or getOrElse(lastResort)

, if everything in the list can be empty as well)

+3


source


Here's a way Option

. It's not much prettier, but everything is called only once. This assumes what you want String

in the result and doesn't care if the second line is empty.



Some(nameFinder.getReliableName)
    .filter(_.nonEmpty)
    .getOrElse(nameFinder.secondBestChoice)

      

+2


source


Option(namefinder.getReliableName) // transforms a potential null into None
.filter(_.trim.nonEmpty) // "" is None, but also "   "
.getOrElse(nameFinder.secondBestChoice)

      

Or better, if you can change getReliableName

to return Option[String]

:

def chooseName(nameFinder: NameFinder): String =
  namefinder.getReliableName getOrElse nameFinder.secondBestChoice

      

Finally, if secondBestChoice

it can fail as well (assuming it returns Option[String]

):

def chooseName(nameFinder: NameFinder): Option[String] =
  namefinder.getReliableName orElse nameFinder.secondBestChoice

      

+2


source


If you need it more than once:

scala> implicit class `nonempty or else`(val s: String) extends AnyVal {
     | def nonEmptyOrElse(other: => String) = if (s.isEmpty) other else s }
defined class nonempty

scala> "abc" nonEmptyOrElse "def"
res2: String = abc

scala> "" nonEmptyOrElse "def"
res3: String = def

      

+2


source


Using the following pattern matching can provide cleaner scalable code,

def chooseName(nameFinder: NameFinder) = {
  nameFinder.getReliableName match {
    case r if r.isEmpty => r
    case _              => nameFinder.secondBestChoice
  }
}

      

0


source







All Articles