我如何摆脱Scala循环?

我如何打破循环?

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循环转换为尾递归?

从FPSDEM 2009的斯卡拉谈话http://www.slideshare.net/Odersky/fosdem-2009-1013261在第22页:

打破并继续斯卡拉没有他们。 为什么? 他们有点必要; 更好地使用许多较小的函数发布如何与闭包进行交互。 他们不需要!

什么是解释?


你有三个(或多个)选项来打破循环。

假设你想总和数字,直到总数大于1000.你试试

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

除非你想停止(总和> 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的旧版本:

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

至少有三个我能想到的理由,故意让它变得不太容易。 首先,在大的代码块中,很容易忽略“继续”和“中断”的陈述,或者认为自己已经脱离了实际情况,或者需要打破两个你无法做到的循环很容易 - 所以标准用法虽然方便,但也存在问题,因此您应该尝试以不同方式构建代码。 其次,斯卡拉拥有各种各样的嵌套,你可能根本没有注意到,所以如果你能摆脱这些事情,你可能会惊讶于代码流在哪里结束(特别是关闭)。 第三,Scala的大多数“循环”实际上并不是正常循环 - 它们是方法调用,它们有自己的循环,或者它们是递归,可能实际上可能不是循环 - 尽管它们循环操作,但很难想出一个一致的方法来知道什么“突破”等应该做的。 所以,要保持一致,更明智的做法是不要有“休息”。

注意 :所有这些功能都等同于您返回sum的值,而不是将其改变。 这些更具惯用斯卡拉。 但是,逻辑保持不变。 ( return成为return x等)。


这已经改变了Scala 2.8,它有一个使用中断的机制。 您现在可以执行以下操作:

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

打破for循环永远不是一个好主意。 如果您使用for循环,则意味着您知道要迭代多少次。 使用2个条件的while循环。

例如

var done = false
while (i <= length && !done) {
  if (i > 1000) {
     done = true;
}
链接地址: http://www.djcxy.com/p/80565.html

上一篇: How do I break out of a loop in Scala?

下一篇: How do I know if a function is tail recursive in F#