I have the following Scala code:
breakable {
someFile.foreach { anotherFile =>
anotherFile.foreach { file =>
try {
val booleanVal = getBoolean(file)
if (booleanVal) break //break out of the try/catch + both loops
} catch {
case e: Throwable => //do something
}
}
}
}
it's the if (booleanVal) break that doesn't work, because it seems like Scala makes it work as an exception. How do I break out of this nested loop?
Move if (booleanVal) break out of try block:
val booleanVal = try {
getBoolean(file)
} catch {
case e: Throwable => //do something
}
if (booleanVal) break // break out of the try/catch + both loops
I suggest you to not use break, for the first this is ugly :) and the second, this is unreadable.
Maybe you would like something like this:
for {
anotherFile <- someFile
file <- anotherFile
b <- Try(getBoolean(file))
if(b)
} /// do something
If you need to do more work in the try block, you can write:
for {
anotherFile <- someFile
file <- anotherFile
} Try{ if(!getBoolean(file)) /* */ } match {
case onSuccess(v) =>
case onFailure(e: Throwable) =>
}
Related
I have code like this:
case class State(state:Long=0,time:Long=0)
def funtionA(int a):Either[error, State]
var a = 123
val inloop = new Breaks
for (s <- funtionA(a) ) {
if (s.state == 1) {
println(s.state )
println("ok")
inloop.break()
}
else {
println( s.state )
println("not ok")
}
}
How to resolve functionA just run one time? I need to run funtionA(a) continue to know s.state ok.
The way to do this loop in a functional language is with a recursive function:
def loop(a: Int): Unit =
funtionA(a) match {
case Right(s) =>
println(s.state)
if (s.state == 1) {
println("ok")
} else {
println("not ok")
loop(a)
}
case Left(e) =>
println(s"error $e")
}
loop(123)
However it looks like this is polling another thread which is not a good idea. Look at using something like Future or Akka Actors to manage the multi-threading.
In the following code, I am reading no. of lines from a file. If something goes wrong, I'll like to close the file pointer. But how can I find out if f contains valid pointer or not?
def countLines(filename:String):Option[Int] = {
try{
val f = Source.fromFile(filename)
println(s"no. of lines ${f.getLines().size}")
Some(f.getLines.size)
} catch {
case ex: FileNotFoundException => {
println(s"file ${filename} not found")
None
}
} finally {
//f might not be a valid pointer depending on when the error occured
}
}
The book I am reading uses var to maintain state (if f is valid or not) but I am trying to avoid it for sake of using only immutable variables.
def countLines(filename:String):Option[Int] = {
var f:Option[Source] = None
try{
f = Some(Source.fromFile(filename))
println(s"no. of lines ${f.get.getLines().size}")
Some(f.get.getLines.size)
} catch {
case ex: FileNotFoundException => {
println(s"file ${filename} not found")
None
}
} finally {
for(i<-f){
println("closing file")
i.close()
}
}
}
A double Try(). This closes the io resource even if the getLines() fails, but only if the fromFile() succeeds.
import scala.util.Try
def countLines(filename: String): Option[Int] =
Try(io.Source.fromFile(filename)).fold(_ => None, {f =>
val count = Try(f.getLines().length)
f.close()
count.toOption
})
What do you think about this?
If you want Scala-way - i think it's good example for your task:
def countLines(filename: String): Try[Int] = Try(Source.fromFile(filename).getLines.toList.size)
def test() = {
val filename = "/etc/passwd"
countLines(filename) match {
case Success(n) => println(n)
case Failure(f) => println(f)
}
}
When n - is a number of our lines, and f - is a Throwable.
How about this:
def countLines(filename: String): Option[Int] = {
val file = Try(Source.fromFile(filename))
val count = file.map(_.getLines().size)
(for {
_ <- count.recoverWith { case _ => file.map(_.close()) }
lineCount <- count
} yield lineCount).toOption
}
Let's analyze it:
If file does not exist we will have failed Try instance and method returns None. In this case you do not need to clear any resources as no actual stream was created.
If getLines fails for any reason or anything else during processing goes south we will close created stream in first line of for comprehension
Hope it helps
Simply, how about this:
def numLines(fileName:String):Option[Int] = {
try {
val f = scala.io.Source.fromFile(fileName)
try { Some(f.getLines.size) }
catch { case ex: IOException =>
Console.err.println("i/o excetion")
None
}
finally { f.close() }
}
catch {
case ex: FileNotFoundException =>
Console.err.println("file not found")
None
}
}
My code throw exception scala.util.control.BreakControl, but I don't know why. Does anyone know?
Some place I use breakable and break, but I don't why cause this exception.
fragment 1
breakable {
for (quaOfLine <- dataOfLine) {
try {
// ... some other code
if (judgeTime(jsonQua.getInt("startTime")) == judgeTime(jsonLine.getInt("startTime"))) {
// ... some other code
if (quaRRIDs.length / RRIDs.length.toFloat >= 0.8 || quaRRIDs.length / RRIDs.length.toFloat <= 1.2) {
var count = 0
breakable {
for (rrid <- RRIDs) {
for (quaRRID <- quaRRIDs) {
if (rrid == quaRRID) {
count += 1
break //break
}
}
}
}
if (count / RRIDs.length.toFloat >= 0.8) {
sameLine = qualifier + "::" + value
break // break
}
}
}
} catch {
case e: Throwable => e.printStackTrace
}
}
}
fragment 2
breakable {
for (quaOfDest <- dataOfDest) {
try {
val qualifier = quaOfDest.getString("qualifier")
val value = quaOfDest.getString("value")
val jsonQua = new JSONObject(value)
val (quaSLon, quaSLat, quaELon, quaELat) = getSELonLat(jsonQua)
if (jsonQua.getInt("timeBucket").toString == judgeTime(jsonLine.getInt("startTime"))) {
someDest = qualifier + "::" + value
break //break
}
} catch {
case e: Throwable => e.printStackTrace
}
}
}
scala.util.control.BreakControl is thrown by the method scala.util.control.Breaks.break. It is used for simulating the break statement from Java. It is used like this:
import scala.util.control.Breaks.{break, breakable}
breakable {
for(i <- 1 until 10) {
println(i)
if(i > 5) break
}
}
BreakControl is a private class so normally it won't be thrown by anything else than break.
This also means that inside a breakable block you shouldn't catch BreakControl yourself. You break inside a try block and then catch all Throwables and print them. BreakControl is a Throwable so it will be caught by you instead of by the breakable method.
If you really want to catch all Exceptions/Throwables, you should do something like this:
import scala.util.control.Breaks.{break, breakable}
import scala.util.control.ControlThrowable
breakable {
for(i <- 1 until 10) {
try {
println(i)
if(i > 5) break
} catch {
case c: ControlThrowable => throw c
case t: Throwable => t.printStackTrace
}
}
}
The Scala Standard Library also includes a special construct for cases like this which lets you catch all Throwables except for fatal ones like OutOfMemoryError or StackOverflowError, and also everything that extends ControlThrowable:
import scala.util.control.NonFatal
try {
//do stuff
} catch {
case NonFatal(e) => e.printStackTrace
}
Is there a better way to ensure resources are properly released - a better way to write the following code ?
val out: Option[FileOutputStream] = try {
Option(new FileOutputStream(path))
} catch {
case _ => None
}
if (out.isDefined) {
try {
Iterator.continually(in.read).takeWhile(-1 != _).foreach(out.get.write)
} catch {
case e => println(e.getMessage)
} finally {
in.close
out.get.flush()
out.get.close()
}
}
Something like that is a good idea, but I'd make it a method:
def cleanly[A,B](resource: => A)(cleanup: A => Unit)(code: A => B): Option[B] = {
try {
val r = resource
try { Some(code(r)) }
finally { cleanup(r) }
} catch {
case e: Exception => None
}
}
(note that we only catch once; if you really want a message printed in one case and not the other, then you do have to catch both like you did). (Also note that I only catch exceptions; catching Error also is usually unwise, since it's almost impossible to recover from.) The method is used like so:
cleanly(new FileOutputStream(path))(_.close){ fos =>
Iterator.continually(in.read).takeWhile(_ != -1).foreach(fos.write)
}
Since it returns a value, you'll get a Some(()) if it succeeded here (which you can ignore).
Edit: to make it more general, I'd really have it return an Either instead, so you get the exception. Like so:
def cleanly[A,B](resource: => A)(cleanup: A => Unit)(code: A => B): Either[Exception,B] = {
try {
val r = resource
try { Right(code(r)) } finally { cleanup(r) }
}
catch { case e: Exception => Left(e) }
}
Now if you get a Right, all went okay. If you get a Left, you can pick out your exception. If you don't care about the exception, you can use .right.toOption to map it into an option, or just use .right.map or whatever to operate on the correct result only if it is there (just like with Option). (Pattern matching is a useful way to deal with Eithers.)
Have a look at Scala-ARM
This project aims to be the Scala Incubator project for Automatic-Resource-Management in the scala library ...
... The Scala ARM library allows users to ensure opening closing of resources within blocks of code using the "managed" method. The "managed" method essentially takes an argument of "anything that has a close or dispose method" and constructs a new ManagedResource object.
Alternatively you can do this with Choppy's Lazy TryClose monad.
val output = for {
fin <- TryClose(in)
fout <- TryClose.wrapWithCloser(new FileOutputStream(path))(out => {out.flush(); out.close();})
} yield wrap(Iterator.continually(fin.read).takeWhile(-1 != _).foreach(fout.get.write))
// Then execute it like this:
output.resolve
More info here: https://github.com/choppythelumberjack/tryclose
(just be sure to import tryclose._ and tryclose.JavaImplicits._)
Experimenting with Scala... I'm trying to define something analogous to the "#" hack in PHP (which means, ignore any exception in the following statement).
I managed to get a definition that works:
def ignoreException(f: () => Unit) = {
try {
f();
}
catch {
case e: Exception => println("exception ignored: " + e);
}
}
And use it like this:
ignoreException( () => { someExceptionThrowingCodeHere() } );
Now here is my question... Is there anyway I can simplify the usage and get rid of the () =>, and maybe even the brackets?
Ultimately I'd like the usage to be something like this:
`#` { someExceptionThrowingCodeHere(); }
# is reserved in Scala (for pattern matching), but would you accept ##?
scala> def ##(block: => Unit): Unit = try {
block
} catch {
case e => printf("Exception ignored: %s%n", e)
}
$at$at: (=> Unit)Unit
scala> ## {
println("before exception")
throw new RuntimeException()
println("after exception")
}
before exception
Exception ignored: java.lang.RuntimeException
I'm not convinced this is a good idea, however ☺
You don't have to use a function as your parameter, a "by-name" parameter will do:
def ignoreException(f: =>Unit) = {
try {
f
}
catch {
case e: Exception => println("exception ignored: " + e)
}
}
ignoreException(someExceptionThrowingCodeHere())
Eric.