Ending a for-comprehension loop when a check on one of the items returns false

jbx picture jbx · Nov 14, 2013 · Viewed 7.9k times · Source

I am a bit new to Scala, so apologies if this is something a bit trivial.

I have a list of items which I want to iterate through. I to execute a check on each of the items and if just one of them fails I want the whole function to return false. So you can see this as an AND condition. I want it to be evaluated lazily, i.e. the moment I encounter the first false return false.

I am used to the for - yield syntax which filters items generated through some generator (list of items, sequence etc.). In my case however I just want to break out and return false without executing the rest of the loop. In normal Java one would just do a return false; within the loop.

In an inefficient way (i.e. not stopping when I encounter the first false item), I could do it:

   (for {
          item <- items
          if !satisfiesCondition(item)
        } yield item).isEmpty

Which is essentially saying that if no items make it through the filter all of them satisfy the condition. But this seems a bit convoluted and inefficient (consider you have 1 million items and the first one already did not satisfy the condition).

What is the best and most elegant way to do this in Scala?

Answer

Akos Krivachy picture Akos Krivachy · Nov 14, 2013

Stopping early at the first false for a condition is done using forall in Scala. (A related question)

Your solution rewritten:

items.forall(satisfiesCondition)

To demonstrate short-circuiting:

List(1,2,3,4,5,6).forall { x => println(x); x < 3 }
1
2
3
res1: Boolean = false

The opposite of forall is exists which stops as soon as a condition is met:

List(1,2,3,4,5,6).exists{ x => println(x); x > 3 }
1
2
3
4
res2: Boolean = true