I found that it\'s a shame that I can\'t return a return value from a such simple construction as try ... catch ... finally
def foo: String = {
In a scala try-catch-finally block, the finally
block is evaluated only for side effects; the value of the block as a whole is the value of the last expression in the try
(if no exception was thrown) or catch
(if one was).
If you look at the output from the compiler, you'll note that it's complaining about the contents of the catch
block, not the finally
:
$ scala test.scala
/tmp/test.scala:12: error: type mismatch;
found : Unit
required: String
case e: Exception => e.printStackTrace()
This is because Exception.printStackTrace()
returns Unit
, so the return type of the function would have to be String
if the try
succeeded and Unit
otherwise.
You can address this by having the catch
block evaluate to a String as well:
catch {
case e: IOException => {
e.printStackTrace()
e.toString()
}
}
Of course, this means there has to be some useful string value you can return even when an error occurs (perhaps ""
?); a more idiomatic approach might be to return an Option[String]
, with the try
block returning Some(in.readLine)
and the catch
block returning None
. In either case, though, the value of both the try
and catch
blocks must match the function signature. The finally
block's type is irrelevant.
For reference, here's a version that passes type checking and works:
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.IOException
def foo: String = {
val in = new BufferedReader(new InputStreamReader(System.in))
try {
in.readLine
}
catch {
case e: IOException => { e.printStackTrace(); e.toString() }
}
finally {
in.close()
}
}
System.out.println("Return value: " + foo)
in.close()
returns Unit, but that's ok because the value of the finally
block is ignored. The try
and catch
blocks both return String.