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?
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
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.
(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:
(1c) Fall back to using a while loop
(2) Throw an exception.
(2a) 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:(3) Put the code into a method and use return.
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
becomesreturn x
, etc.).Close to your solution would be this:
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.
This has changed in Scala 2.8 which has a mechanism for using breaks. You can now do the following:
I got a situation like the code below
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.
Clever use of
find
method for collection will do the trick for you.