我如何打破一个循环?

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
    }
}

如何将嵌套for循环转换为尾递归?

来自FOSDEM 2009 Scala Talk http://www.slideshare.net/Odersky/fosdem-2009-1013261 第22页:

中断并继续 Scala没有它们。为什么? 它们有点迫不得已;最好使用许多较小的函数 发布如何与闭包交互。 他们是不需要的!

怎么解释呢?


当前回答

在scala中我们能做的就是

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;
       } } } }

输出:

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

其他回答

您有三个(大约)选项可以跳出循环。

假设您希望将数字相加,直到总数大于1000。你尝试

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

除非你想在(sum > 1000)时停止。

怎么办呢?有几种选择。

(1a)使用一些包含你要测试的条件的结构。

var sum = 0
(0 to 1000).iterator.takeWhile(_ => sum < 1000).foreach(i => sum+=i)

(警告——这取决于takeWhile测试和foreach在评估期间如何交织的细节,并且可能不应该在实践中使用!)

(1b)使用尾递归代替for循环,利用Scala中编写新方法的简单性:

var sum = 0
def addTo(i: Int, max: Int) {
  sum += i; if (sum < max) addTo(i+1,max)
}
addTo(0,1000)

(1c)回到使用while循环

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

(2)抛出异常。

object AllDone extends Exception { }
var sum = 0
try {
  for (i <- 0 to 1000) { sum += i; if (sum>=1000) throw AllDone }
} catch {
  case AllDone =>
}

(2a)在Scala 2.8+中,这已经被预先打包在Scala .util.control. breaks中,使用的语法看起来很像你熟悉的C/Java break:

import scala.util.control.Breaks._
var sum = 0
breakable { for (i <- 0 to 1000) {
  sum += i
  if (sum >= 1000) break
} }

(3)将代码放入方法并使用return。

var sum = 0
def findSum { for (i <- 0 to 1000) { sum += i; if (sum>=1000) return } }
findSum

This is intentionally made not-too-easy for at least three reasons I can think of. First, in large code blocks, it's easy to overlook "continue" and "break" statements, or to think you're breaking out of more or less than you really are, or to need to break two loops which you can't do easily anyway--so the standard usage, while handy, has its problems, and thus you should try to structure your code a different way. Second, Scala has all sorts of nestings that you probably don't even notice, so if you could break out of things, you'd probably be surprised by where the code flow ended up (especially with closures). Third, most of Scala's "loops" aren't actually normal loops--they're method calls that have their own loop, or they are recursion which may or may not actually be a loop--and although they act looplike, it's hard to come up with a consistent way to know what "break" and the like should do. So, to be consistent, the wiser thing to do is not to have a "break" at all.

注意:在返回sum的值而不是原地改变它的地方,所有这些函数都有等价的功能。这些是更习惯的Scala。然而,逻辑是一样的。(return变成return x,等等)。

跳出for循环从来都不是一个好主意。如果你正在使用for循环,这意味着你知道你想要迭代多少次。使用带有两个条件的while循环。

例如

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

我遇到了类似下面代码的情况

 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}
    }
  }

我正在使用一个java库和机制是ctx。read在找不到任何东西时抛出异常。 我被困在这样的情况中:当抛出异常时,我必须打破循环,但是scala.util.control. break .break使用异常来打破循环,并且它在catch块中,因此它被捕获。

我有一个丑陋的方法来解决这个问题:第一次执行循环,并获得实际长度的计数。 然后用它来做第二个循环。

当你使用一些java库时,从Scala中解脱出来并不是那么好。

第三方易碎包是一种可能的替代方案

https://github.com/erikerlandson/breakable

示例代码:

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))
// 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;
   }
}

使用Break模块 http://www.tutorialspoint.com/scala/scala_break_statement.htm