Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala - can 'for-yield' clause yields nothing for some condition?

In Scala language, I want to write a function that yields odd numbers within a given range. The function prints some log when iterating even numbers. The first version of the function is:

def getOdds(N: Int): Traversable[Int] = {
  val list = new mutable.MutableList[Int]
  for (n <- 0 until N) {
    if (n % 2 == 1) {
      list += n
    } else {
      println("skip even number " + n)
    }
  }
  return list
}

If I omit printing logs, the implementation become very simple:

def getOddsWithoutPrint(N: Int) =
  for (n <- 0 until N if (n % 2 == 1)) yield n

However, I don't want to miss the logging part. How do I rewrite the first version more compactly? It would be great if it can be rewritten similar to this:

def IWantToDoSomethingSimilar(N: Int) =
  for (n <- 0 until N) if (n % 2 == 1) yield n else println("skip even number " + n)
like image 995
pocorall Avatar asked Sep 16 '12 13:09

pocorall


2 Answers

def IWantToDoSomethingSimilar(N: Int) = 
  for {
    n <- 0 until N
    if n % 2 != 0 || { println("skip even number " + n); false }
  } yield n

Using filter instead of a for expression would be slightly simpler though.

like image 194
Luigi Plinge Avatar answered Oct 27 '22 21:10

Luigi Plinge


I you want to keep the sequentiality of your traitement (processing odds and evens in order, not separately), you can use something like that (edited) :

def IWantToDoSomethingSimilar(N: Int) =
  (for (n <- (0 until N)) yield {
    if (n % 2 == 1) {
        Option(n) 
    } else {
        println("skip even number " + n)
        None
    }
  // Flatten transforms the Seq[Option[Int]] into Seq[Int]
  }).flatten

EDIT, following the same concept, a shorter solution :

def IWantToDoSomethingSimilar(N: Int) = 
    (0 until N) map {
        case n if n % 2 == 0 => println("skip even number "+ n)
        case n => n
    } collect {case i:Int => i}
like image 6
jwinandy Avatar answered Oct 27 '22 20:10

jwinandy