[scala] How do I break out of a loop in Scala?

How do I break out a loop?

var largest=0
for(i<-999 to 1 by -1) {
    for (j<-i to 1 by -1) {
        val product=i*j
        if (largest>product)
            // I want to break out here
        else
           if(product.toString.equals(product.toString.reverse))
              largest=largest max product
    }
}

How do I turn nested for loops into tail recursion?

From Scala Talk at FOSDEM 2009 http://www.slideshare.net/Odersky/fosdem-2009-1013261 on the 22nd page:

Break and continue Scala does not have them. Why? They are a bit imperative; better use many smaller functions Issue how to interact with closures. They are not needed!

What is the explanation?

This question is related to scala for-loop break tail-recursion

The answer is


Since there is no break in Scala yet, you could try to solve this problem with using a return-statement. Therefore you need to put your inner loop into a function, otherwise the return would skip the whole loop.

Scala 2.8 however includes a way to break

http://www.scala-lang.org/api/rc/scala/util/control/Breaks.html


It is never a good idea to break out of a for-loop. If you are using a for-loop it means that you know how many times you want to iterate. Use a while-loop with 2 conditions.

for example

var done = false
while (i <= length && !done) {
  if (sum > 1000) {
     done = true
  }
}

// import following package
import scala.util.control._

// create a Breaks object as follows
val loop = new Breaks;

// Keep the loop inside breakable as follows
loop.breakable{
// Loop will go here
for(...){
   ....
   // Break will go here
   loop.break;
   }
}

use Break module http://www.tutorialspoint.com/scala/scala_break_statement.htm


To add Rex Kerr answer another way:

  • (1c) You can also use a guard in your loop:

     var sum = 0
     for (i <- 0 to 1000 ; if sum<1000) sum += i
    

Here is a tail recursive version. Compared to the for-comprehensions it is a bit cryptic, admittedly, but I'd say its functional :)

def run(start:Int) = {
  @tailrec
  def tr(i:Int, largest:Int):Int = tr1(i, i, largest) match {
    case x if i > 1 => tr(i-1, x)
    case _ => largest
  }

  @tailrec
  def tr1(i:Int,j:Int, largest:Int):Int = i*j match {
    case x if x < largest || j < 2 => largest
    case x if x.toString.equals(x.toString.reverse) => tr1(i, j-1, x)
    case _ => tr1(i, j-1, largest)
  }

  tr(start, 0)
}

As you can see, the tr function is the counterpart of the outer for-comprehensions, and tr1 of the inner one. You're welcome if you know a way to optimize my version.


import scala.util.control._

object demo_brk_963 
{
   def main(args: Array[String]) 
   {
      var a = 0;
      var b = 0;
      val numList1 = List(1,2,3,4,5,6,7,8,9,10);
      val numList2 = List(11,12,13);

      val outer = new Breaks; //object for break
      val inner = new Breaks; //object for break

      outer.breakable // Outer Block
      {
         for( a <- numList1)
         {
            println( "Value of a: " + a);

            inner.breakable // Inner Block
            {
               for( b <- numList2)
               {
                  println( "Value of b: " + b);

                  if( b == 12 )
                  {
                      println( "break-INNER;");
                       inner.break;
                  }
               }
            } // inner breakable
            if( a == 6 )
            {
                println( "break-OUTER;");
                outer.break;
            }
         }
      } // outer breakable.
   }
}

Basic method to break the loop, using Breaks class. By declaring the loop as breakable.


Below is code to break a loop in a simple way

import scala.util.control.Breaks.break

object RecurringCharacter {
  def main(args: Array[String]) {
    val str = "nileshshinde";

    for (i <- 0 to str.length() - 1) {
      for (j <- i + 1 to str.length() - 1) {

        if (str(i) == str(j)) {
          println("First Repeted Character " + str(i))
          break()     //break method will exit the loop with an Exception "Exception in thread "main" scala.util.control.BreakControl"

        }
      }
    }
  }
}

I am new to Scala, but how about this to avoid throwing exceptions and repeating methods:

object awhile {
def apply(condition: () => Boolean, action: () => breakwhen): Unit = {
    while (condition()) {
        action() match {
            case breakwhen(true)    => return ;
            case _                  => { };
        }
    }
}
case class breakwhen(break:Boolean);

use it like this:

var i = 0
awhile(() => i < 20, () => {
    i = i + 1
    breakwhen(i == 5)
});
println(i)

if you don’t want to break:

awhile(() => i < 20, () => {
    i = i + 1
    breakwhen(false)
});

Simply We can do in scala is

scala> import util.control.Breaks._

scala> object TestBreak {
       def main(args : Array[String]) {
         breakable {
           for (i <- 1 to 10) {
             println(i)
             if (i == 5)
               break;
       } } } }

output :

scala> TestBreak.main(Array())
1
2
3
4
5

This has changed in Scala 2.8 which has a mechanism for using breaks. You can now do the following:

import scala.util.control.Breaks._
var largest = 0
// pass a function to the breakable method
breakable { 
    for (i<-999 to 1  by -1; j <- i to 1 by -1) {
        val product = i * j
        if (largest > product) {
            break  // BREAK!!
        }
        else if (product.toString.equals(product.toString.reverse)) {
            largest = largest max product
        }
    }
}

I got a situation like the code below

 for(id<-0 to 99) {
    try {
      var symbol = ctx.read("$.stocks[" + id + "].symbol").toString
      var name = ctx.read("$.stocks[" + id + "].name").toString
      stocklist(symbol) = name
    }catch {
      case ex: com.jayway.jsonpath.PathNotFoundException=>{break}
    }
  }

I am using a java lib and the mechanism is that ctx.read throw a Exception when it can find nothing. I was trapped in the situation that :I have to break the loop when a Exception was thrown, but scala.util.control.Breaks.break using Exception to break the loop ,and it was in the catch block thus it was caught.

I got ugly way to solve this: do the loop for the first time and get the count of the real length. and use it for the second loop.

take out break from Scala is not that good,when you are using some java libs.


I don't know how much Scala style has changed in the past 9 years, but I found it interesting that most of the existing answers use vars, or hard to read recursion. The key to exiting early is to use a lazy collection to generate your possible candidates, then check for the condition separately. To generate the products:

val products = for {
  i <- (999 to 1 by -1).view
  j <- (i to 1 by -1).view
} yield (i*j)

Then to find the first palindrome from that view without generating every combination:

val palindromes = products filter {p => p.toString == p.toString.reverse}
palindromes.head

To find the largest palindrome (although the laziness doesn't buy you much because you have to check the entire list anyway):

palindromes.max

Your original code is actually checking for the first palindrome that is larger than a subsequent product, which is the same as checking for the first palindrome except in a weird boundary condition which I don't think you intended. The products are not strictly monotonically decreasing. For example, 998*998 is greater than 999*997, but appears much later in the loops.

Anyway, the advantage of the separated lazy generation and condition check is you write it pretty much like it is using the entire list, but it only generates as much as you need. You sort of get the best of both worlds.


Close to your solution would be this:

var largest = 0
for (i <- 999 to 1 by -1;
  j <- i to 1 by -1;
  product = i * j;
  if (largest <= product && product.toString.reverse.equals (product.toString.reverse.reverse)))
    largest = product

println (largest)

The j-iteration is made without a new scope, and the product-generation as well as the condition are done in the for-statement (not a good expression - I don't find a better one). The condition is reversed which is pretty fast for that problem size - maybe you gain something with a break for larger loops.

String.reverse implicitly converts to RichString, which is why I do 2 extra reverses. :) A more mathematical approach might be more elegant.


The third-party breakable package is one possible alternative

https://github.com/erikerlandson/breakable

Example code:

scala> import com.manyangled.breakable._
import com.manyangled.breakable._

scala> val bkb2 = for {
     |   (x, xLab) <- Stream.from(0).breakable   // create breakable sequence with a method
     |   (y, yLab) <- breakable(Stream.from(0))  // create with a function
     |   if (x % 2 == 1) continue(xLab)          // continue to next in outer "x" loop
     |   if (y % 2 == 0) continue(yLab)          // continue to next in inner "y" loop
     |   if (x > 10) break(xLab)                 // break the outer "x" loop
     |   if (y > x) break(yLab)                  // break the inner "y" loop
     | } yield (x, y)
bkb2: com.manyangled.breakable.Breakable[(Int, Int)] = com.manyangled.breakable.Breakable@34dc53d2

scala> bkb2.toVector
res0: Vector[(Int, Int)] = Vector((2,1), (4,1), (4,3), (6,1), (6,3), (6,5), (8,1), (8,3), (8,5), (8,7), (10,1), (10,3), (10,5), (10,7), (10,9))

Just use a while loop:

var (i, sum) = (0, 0)
while (sum < 1000) {
  sum += i
  i += 1
}

Clever use of find method for collection will do the trick for you.

var largest = 0
lazy val ij =
  for (i <- 999 to 1 by -1; j <- i to 1 by -1) yield (i, j)

val largest_ij = ij.find { case(i,j) =>
  val product = i * j
  if (product.toString == product.toString.reverse)
    largest = largest max product
  largest > product
}

println(largest_ij.get)
println(largest)

An approach that generates the values over a range as we iterate, up to a breaking condition, instead of generating first a whole range and then iterating over it, using Iterator, (inspired in @RexKerr use of Stream)

var sum = 0
for ( i <- Iterator.from(1).takeWhile( _ => sum < 1000) ) sum += i

Ironically the Scala break in scala.util.control.Breaks is an exception:

def break(): Nothing = { throw breakException }

The best advice is: DO NOT use break, continue and goto! IMO they are the same, bad practice and an evil source of all kind of problems (and hot discussions) and finally "considered be harmful". Code block structured, also in this example breaks are superfluous. Our Edsger W. Dijkstra† wrote:

The quality of programmers is a decreasing function of the density of go to statements in the programs they produce.


Examples related to scala

Intermediate language used in scalac? Why does calling sumr on a stream with 50 tuples not complete Select Specific Columns from Spark DataFrame Joining Spark dataframes on the key Provide schema while reading csv file as a dataframe how to filter out a null value from spark dataframe Fetching distinct values on a column using Spark DataFrame Can't push to the heroku Spark - Error "A master URL must be set in your configuration" when submitting an app Add jars to a Spark Job - spark-submit

Examples related to for-loop

List append() in for loop Prime numbers between 1 to 100 in C Programming Language Get current index from foreach loop how to loop through each row of dataFrame in pyspark TypeScript for ... of with index / key? Is there a way in Pandas to use previous row value in dataframe.apply when previous value is also calculated in the apply? Python for and if on one line R for loop skip to next iteration ifelse How to append rows in a pandas dataframe in a for loop? What is the difference between ( for... in ) and ( for... of ) statements?

Examples related to break

How to break a while loop from an if condition inside the while loop? illegal use of break statement; javascript How can I use break or continue within for loop in Twig template? break statement in "if else" - java Regarding Java switch statements - using return and omitting breaks in each case Is it bad practice to use break to exit a loop in Java? break/exit script Breaking out of a for loop in Java How to break out of while loop in Python? How to kill a while loop with a keystroke?

Examples related to tail-recursion

How do I break out of a loop in Scala? What is tail call optimization? What is tail recursion?