You have three (or so) options to break out of loops.
Suppose you want to sum numbers until the total is greater than 1000. You try
var sum = 0
for (i <- 0 to 1000) sum += i
except you want to stop when (sum > 1000).
What to do? There are several options.
(1a) Use some construct that includes a conditional that you test.
var sum = 0
(0 to 1000).iterator.takeWhile(_ => sum < 1000).foreach(i => sum+=i)
(warning--this depends on details of how the takeWhile test and the foreach are interleaved during evaluation, and probably shouldn't be used in practice!).
(1b) Use tail recursion instead of a for loop, taking advantage of how easy it is to write a new method in Scala:
var sum = 0
def addTo(i: Int, max: Int) {
sum += i; if (sum < max) addTo(i+1,max)
}
addTo(0,1000)
(1c) Fall back to using a while loop
var sum = 0
var i = 0
while (i <= 1000 && sum <= 1000) { sum += i; i += 1 }
(2) In Scala 3.3+, use boundaries instead (for more info):
import scala.util.boundary, boundary.break
boundary {
for i <- 0 to 1000 do
sum += i
if sum >= 1000 then break()
}
(3) Throw an exception.
object AllDone extends Exception { }
var sum = 0
try {
for (i <- 0 to 1000) { sum += i; if (sum>=1000) throw AllDone }
} catch {
case AllDone =>
}
(3a) In Scala 2.8+ this is already pre-packaged in scala.util.control.Breaks
using syntax that looks a lot like your familiar old break from C/Java:
import scala.util.control.Breaks._
var sum = 0
breakable { for (i <- 0 to 1000) {
sum += i
if (sum >= 1000) break
} }
(4) Put the code into a method and use 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.
Note: There are functional equivalents of all of these where you return the value of sum
rather than mutate it in place. These are more idiomatic Scala. However, the logic remains the same. (return
becomes return x
, etc.).
i
andj
. If this code runs to completion without breaking out of the loop, the result is906609
but by breaking out of the loop early, the result is90909
so breaking out of the loop is not making the code "more efficient" as it is altering the result. – Droopy