I'm unhappy with the rule about variable scope in a try block not being shared with associated catch and finally blocks. Specifically it leads to code like the following:
var v: VType = null
try {
v = new VType()
}
catch {
case e => // handle VType constructor failure (can reference v)
}
finally {
// can reference v.
}
As opposed to:
try {
val v = new VType()
}
catch {
case e => // handle VType constructor failure (can reference v)
}
finally {
// can reference v.
}
Can anyone please explain or justify why this rule from Java persists?
and / or is there hope that this could change?
Thanks!
UPDATE
Many thanks for all the responses to date.
The consensus seems to imply "just get on with it" and I'm starting to conclude that perhaps technically what I want is either unsound, not worth the effort or hard to achieve.
I like Rex Kerr's answer but how would the original code above be wrapped in a method call without introducing a local var in the method body?
My own efforts weren't too good, using a by-name parameter to delay construction until safely in the try block works but still doesn't give me access to the constructed (or not) object in the catch or finally blocks.
Just "try" this ;)
val v = try { new VType() } catch { case e: Exception => /* ... */ }
In Scala, try is an expression, so it has a value.
You might be thinking about the problem the wrong way. Why do you want so much stuff in your try/catch/finally block? In your code,
try { val v = new VType() }
the exception could be thrown before you get v back, so you can't safely reference v. But if you can't reference v, then what can you do on the finally side that won't break or throw its own exception or have some other ill-defined behavior? What if you create v but fail to create w, but disposal requires having w as well? (Or doesn't?) It ends up being a mess.
But if you're coming from Java, there are a few things that can help you write try/catch/finally blocks in a sensible way.
One thing you can do is catch certain classes of exceptions and turn them into options instead:
def s2a(s: String) = try { Some(s.toInt) } catch { case nfe: NumberFormatException => None}
Another thing you can do is to create your own resource manager
def enclosed[C <: { def close() }](c: C)(f: C => Unit) {
try { f(c) } finally { c.close() }
}
enclosed(new FileInputStream(myFile))(fis => {
fis.read...
}
Or you can create your own shut-down-and-escape-safely method within another method:
val r = valuableOpenResource()
def attempt[F](f: => F) = {
try { f } catch { case re: ReasonableException => r.close() throw re }
}
doSomethingSafe()
attempt( doSomethingDangerous() )
doSomethingElseSafe()
r.close()
Between these different ways of handling things, I've not had much need to create vars to hold variables that I want to clean up later or otherwise deal with in catch or finally blocks.
How would this code work?
try
{
int i = 0;
// Do stuff...
Foo x = new Foo();
// Do more stuff...
Bar y = new Bar();
}
catch
{
// Print the values of i, x, and y.
}
What are the values of i, x, and y? Did y even get declared before we landed in the catch block?
The exception concept is not a subroutine of the try block, it is an alternate code flow. That makes at try-catch control block more like an "if anything untoward happens" then insert these (catch) lines in the current position of the try block, as needed.
With that in mind, it isn't clear if Val v = Type(); is going to be defined or not because the exception could (theoretically) be thrown before Val v = Type(); is evaluated. Yes, Val v is the first line in the block, but there are JVM errors which could be thrown before it.
Finally is another code construct which adds and alternate, but required, code flow the end of leaving the try-catch construct. Again, we have no idea how much (if any) of the try block was evaluated before the finally block was called, so we cannot depend on the declared variables within that block.
The only alternative left (now that we cannot use try block variables, due to their uncertainty of existence) is to use variable outside of the entire try-catch-finally construct for communications between the individual code blocks.
Does it suck? Maybe a little. Do we have anything that's better? Probably not. Putting the variable declarations outside of the block makes it obvious that the variables will have been defined prior to whatever control structure you process through in a try-catch-finally scenario.
If your main concern is that v should be immutable, you might get close to what you want with:
case class VType(name: String) {
// ... maybe throw an exception ...
}
val v = LazyVal(() => new VType())
try {
// do stuff with v
println(v.name) // implicitly converts LazyVal[VType] to VType
// do other unsafe stuff
} catch {
case e => // handle VType constructor failure
// can reference v after verifying v.isInitialized
} finally {
// can reference v after verifying v.isInitialized
if (v.isInitialized) v.safelyReleaseResources
}
where LazyVal is defined as
/**
* Based on DelayedLazyVal in the standard library
*/
class LazyVal[T](f: () => T) {
#volatile private[this] var _inited = false
private[this] lazy val complete = {
val v = f()
_inited = true
v
}
/** Whether the computation is complete.
*
* #return true if the computation is complete.
*/
def isInitialized = _inited
/** The result of f().
*
* #return the result
*/
def apply(): T = complete
}
object LazyVal {
def apply[T](f: () => T) = new LazyVal(f)
implicit def lazyval2val[T](l: LazyVal[T]): T = l()
}
It would be nice if we could use lazy val v = new VType(), but AFAIK there is no mechanism to safely determine whether a lazy val has been initialized.
Here's another alternative:
object Guard {
type Closing = {def close:Unit}
var guarded: Stack[Set[Closing]] = Stack()
def unapply(c: Closing) = {
guarded.push(guarded.pop + c)
Some(c)
}
private def close {println("Closing"); guarded.head.foreach{c => c.close}}
private def down {println("Adding Set"); guarded.push(Set())}
private def up {println("Removing Set"); guarded.pop}
def carefully(f: => Unit) {
down
try {f}
finally {close; up}
}
}
You can use it like this:
import Guard.carefully
class File {def close {println("Closed File")}}
class BadFile {def close {println("Closed Bad File")}; throw new Exception("BadFile failed")}
carefully {
val Guard(f) = new File
val Guard(g) = new File
val Guard(h) = new BadFile
}
which results in
Adding Set
Closing
Closed File
Closed File
java.lang.Exception: BadFile failed
So the first two files are created, then when the third constructor fails, the first two are automatically closed. All files are values.
Your example does not concretize why you need the finally clause. If VType is e.g. a resource that needs do be closed, you could do it one of the following ways.
1) You want to reference v after using it throws an exception:
try {
val v = new VType // may throw
try {
v.someThing // may throw
}
catch {
case ex => println("Error on doing something with v :" + v + ex) // or whatever
}
finally {
v.close()
}
}
catch {
case ex => println("Error on getting or closing v: " + ex) // v might not be constructed
}
2) You don't care about v in the catch clause:
try {
val v = new VType // may throw
try {
v.someThing // may throw
}
finally {
v.close()
}
}
catch {
case ex => println("Error on either operation: " + ex)
}
In either case, you get rid of the var.
Related
so I have a method which already has a try block that throws ExceptionA. Now I need to put another try block where this method is being called and needs to throw an exception with some added details. Something like this:
method inner():
try{
//some logic
} catch {
throw new ExceptionA("exceptionA occurred")
}
method outer():
identifier = fromSomeDBCallPrivateToOuter()
try{
inner()
} catch {
// now either
// throw new Exception("Error with identifier" + identifier)
// or
// append identifier to thrown error from inner()
}
Can someone please provide any insight or suggestion on how to do this in Scala? Thanks in advance!
What you have in your snippet would work as written (if you correct the syntax), with a caveat, that exceptions are immutable (and even they weren't, it's still not a good idea to mutate them), so, instead of "appending" to exception, you'd need to create a new one, and set the original as cause.
It is more idiomatic in scala though to use Try monad instead of the "procedural" try/catch blocks. Something like this:
case class ExceptionB(id: String, original: ExceptionA)
extends Exception(s"Badness happened with id $id", original)
def outer(): Try[ReturnType] =
val id = getId()
Try {
inner
} recover {
case e: ExceptionA if iWannaNewException => throw new Exception(s"Id: id")
case e: ExceptionA => throw ExceptionB(id, e)
}
You can also use Either structure. This structure can return Right(value) if function completes without error or Left(message) containing information about error. You can adapt your code like below one:
def inner(): Either[String, Int] = {
if (checkSomeStuff()) Left("Cannot assigne identifier")
else Right(doSomeStuff())
}
def outer(): Either[String, Int] = {
inner() match {
case Left(error) => {
println("There is an error: " + error)
// you can also throw new Exception(s"Some info about $error") here
}
case Right(identifier) => {
println("Identifier : " + identifier)
doSomeStuffWithId() // do some staff for id
}
}
}
If you want to use Exceptions you need to choose who will handle the error case (in the inner or in the outer function).
I have a function that wraps the result of another function in a Promise. I wanted to promote this into a lift function so that I could sort of re-use it elsewhere. Here are the original definitions:
val abc = Promise[MyType]()
try {
val suck = abc.success(someOtherFunction(intParam1, intParam2))
} catch {
case ex: Exception => p.failure(ex)
}
So what I eventually did was the following:
def myLiftFunc[X](x: X) (op: => X): Promise[X] = {
val p = Promise[X]()
try {
p.success(op)
} catch {
case NonFatal(ex) =>
p.failure(ex)
}
p
}
How can I re-use this? I mean, the second argument that I pass in should be a thunk so that I could just pass in any function body irrespective of the parameters that function body would require!
When I call the lifted function as:
myLiftFunc(someOtherFunction(intParam1, intParam2))
This is of type Int => Promise[Int], where the someOtherFunction returns an Int. I just want Promise[Int] when I call myLiftFunc!
You might be interested in the Promise.fromTry method. That method uses the Try idiom from scala.util, which is a useful structure that allows you to treat a try...catch statement more like a traditional constructs:
Promise.fromTry { Try { someOtherFunction(intParam1, intParam2) } }
If you wanted to right your own helper (so that the Try part is unnecessary, you could try something like:
def myLiftFunc[X](op: => X): Promise[X] = Promise.fromTry(Try(op))
This would allow you to do:
myLiftFunc { /*arbitrary logic*/ }
myLiftFunc(1 + 4).future.value.get //Success(5)
myLiftFunc(1/0).future.value.get //Failure(java.lang.ArithmeticException: / by zero)
I have this code in Scala, a object should be value not a variable, How can I initialize the a object in the try block?
object SomeObject {
private val a : SomeClass
try {
a=someThing // this statement may throw an exception
}
catch {
case ex: Exception=> {
ex.printStackTrace()
}
}
}
Scala tries to avoid undefined/null values. However, you can solve the problem by giving return values for the cases if the try fails and initializing a with the whole try expression:
private val a: SomeClass =
try {
someThing // this statement may throw an exception
} catch {
case ex: Exception => {
ex.printStackTrace()
someDefault
}
}
Update: In Scala it would be probably more idiomatic to use Try from scala.util:
val x : Int =
Try({
someThing
}).recoverWith({
// Just log the exception and keep it as a failure.
case (ex: Throwable) => ex.printStackTrace; Failure(ex);
}).getOrElse(1);
Try allows you to compose computations that can fail with an exception in various ways. For example, if you have two computations of type Try you can call
thing1.orElse(thing2).getOrElse(someDefault)
This runs thing1 and returns its result, if it's successful. If it fails, it continues with thing2. If it fails too, returns someDefault. You can also use recover or recoverWith to recover from some exceptions using partial functions (and potentially reuse those partial functions).
Since in Scala blocks have return values, and the last expression is the return value per default, you can do this:
object SomeObject {
private val a : SomeClass = { //this additional block not necessary, but added for clarity
try {
someThing // this statement may throw an exception
}
catch {
case ex: Exception=> {
ex.printStackTrace()
null
}
}
}
}
. However, I have to add that this looks like you're trying to accomplish something potentially blowing up in your face later - you will need null checks in any code that uses the value.
I have the following snippet of code:
val oldStep = step
try {
someDangerousActionPotentiallyModifyingStep()
} finally {
step = oldStep
}
Is it possible to write a generic helper method to abstract away the pattern? Then I could use the helper method like this:
remember(step) {
someDangerousActionPotentiallyModifyingStep()
}
Of course the following approach does not work, because Scala does not support pass by reference:
def remember[T](x: T)(action: => Unit) {
val previousValue = x
try {
action
} finally {
x = previousValue
}
}
I solved the problem by changing the step data member into an implicit parameter. That way, I never have to restore the old value of step, because its value never changes inside the same scope :)
The problem is that a var does not give you enough control to do what you want to do.
As a direct answer to your question: you need an object with an update method instead of a field. Something like this:
class Box[T](var value:T) {
def apply = value
def update(newValue:T) { value = newValue }
override def toString = value.toString
}
Then you can solve your problem like this:
def remember[T](box:Box[T])(action: =>Unit) {
val prev = box.apply
try {
action
} catch {
case _ => box() = prev
}
}
val step = new Box(0)
// working update
remember(step) { step() = 4 }
// step is now 4
// aborted update
remember(step) { step() = 5; throw new Exception }
// step is still 4
But note that this is really not very idiomatic scala. You should try to make your someDangerousActionPotentiallyModifyingStep a side-effect-free function that returns the new step.
Basically like this:
try {
step = someDangerousFunctionOfStep(step)
} catch {
case _ => // we don't have to do anything because step is still the same
}
If that is not possible for some reason, you might want to investigate Akka agents, which are conceptually similar to the Box above, except with the difference that they are thread-safe and can be used in a transactional way.
Here is how you would use akka agents to solve the problem:
First you need an actor system:
implicit val actorSystem = akka.actor.ActorSystem("test")
Then you can define an agent containing the step value
val step = akka.agent.Agent(0)
Now you can update it in a transaction:
import scala.concurrent.stm._
atomic { txn => step() = 4 }
// step.get will now return 4
atomic { txn => step() = 5; throw new Exception }
// step.get will still return 5. You will have to catch the exception if you don't want
// it to propagate outward
The real power of akka agents comes when you have multiple agents and update them atomically. See the akka agents docs for the canonical "account transfer" transaction example.
It's pretty ugly (and an affront to immutability), but you could try something like this:
def remember[T](newT:T, get: => T, set:(T) => Unit)(action: => Unit) = {
var old = get
set(newT)
try{
action
}
finally{
set(old)
}
}
And then use it like this:
var x = "hello"
remember[String]("world", x, x = _){
//do something dangerous here
}
I think you're looking for Loan pattern.
http://blog.knoldus.com/2012/11/16/scalaknol-understanding-loan-pattern/
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._)