How to return a yielded value from a for-loop in scala?

How to return a yielded value from a for-loop in scala?

There is no usual for-loops like in java in scala. for-yield is not the same as for-loop. Its just syntactic sugar for flatMap, map and withFilter functions combinations. Also in scala is better not to use return keyword. The language based on expressions which has return value and return word can break the logic and another developers cant expect that.

In your case it will be better to use find for looking some specific element in some collection by predicate:

def getBeforeToken(token: TSourceToken): TSourceToken = {
  val tokens = token.container
  val index = token.posinlist

  (index - 1 to 0 by -1)
    .find(i => tokens.get(i).toString.trim.length != 0)
    .fold(token)(i => tokens.get(i))
}

a for comprehension is not the right tool for this problem: its for mapping, not for finding.

For a straight-forward re-write that just re-writes your java code to scala, use a while loop:

def getBeforeToken(token: TSourceToken): TSourceToken = {
  val tokens = token.container
  var i = index - 1
  while (i >= 0) {
    val currentToken = tokens.get(i)
    if (currentToken.toString.trim.length != 0) return currentToken
    i -= 1
  }
  token
}

if token.container is some collection though, youd probably write it without explicit iteration:

def getBeforeToken(token: TSoruceToken): TSourceToken =
  token.container.reverseIterator.collectFirst {
    case t if t.toString.trim.length != 0 => t
  }.getOrElse(token)

While in the process of migrating, it may be smart to stick with the first though, to get the almost-mechnical translation done as quick as possible, before trying to up the scala code quality.

How to return a yielded value from a for-loop in scala?

You can read a lot about Scala yield. Here are some nice articles:

But I think that is the wrong way to approach this in Scala. Scala is a functional programming language, and you can use its capabalities.

Assuming TSourceToken is case class having two members:

case class TSourceToken(container: Seq[String], posinlist: Int)

Where you want to choose the last token that is not empty from the last posinlist ones. There are many ways to achieve that. One way I was thinking about is:

val tokens = TSourceToken(Seq(,    ,   n   , real token, tt,    ,   nn  , token to ignore), 5)
val token = tokens.container.take(tokens.posinlist).filter(_.trim.nonEmpty).last

token will have real token, as you expect. Code run can be found at Scastie.

Leave a Reply

Your email address will not be published.