How do I break out of a loop in Scala?

2019-01-03 07:14发布

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?

18条回答
Explosion°爆炸
2楼-- · 2019-01-03 08:08

Just use a while loop:

var (i, sum) = (0, 0)
while (sum < 1000) {
  sum += i
  i += 1
}
查看更多
贼婆χ
3楼-- · 2019-01-03 08:08

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)
});
查看更多
我命由我不由天
4楼-- · 2019-01-03 08:10

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.

查看更多
看我几分像从前
5楼-- · 2019-01-03 08:11

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
查看更多
Viruses.
6楼-- · 2019-01-03 08:13

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
    
查看更多
做个烂人
7楼-- · 2019-01-03 08:14

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.

查看更多
登录 后发表回答