The problem is that in the case of an exception, there is no value to return. So you have to decide what value to return in such a case. It can be an empty list (if you really don't care about handling the error - not recommended!):
def method1(arg: String*): List[String] =
try {
new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString)
} catch {
case e: Exception => { e.printStackTrace(); Nil; }
}
A standard Scala way would be to return an Option
, which makes it clear to the caller what happened:
def method1(arg: String*): Option[List[String]] =
try {
Some(new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString))
} catch {
case e: Exception => { e.printStackTrace(); None; }
}
or perhaps return the exception itself:
def method1(arg: String*): Either[Exception,List[String]] =
try {
Right(new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString))
} catch {
case e: Exception => Left(e)
}
Since this pattern is relativelly common, there is a special Scala class Try
just for this purpose, that gives these concepts meaningful names and adds many helpful methods. Try[A]
encapsulates the result of a computation that returns A
, or an exception if the computation failed:
sealed abstract class Try[+T]
final case class Success[+T](value: T) extends Try[T]
final case class Failure[+T](exception: Throwable) extends Try[T]
so a literal rewrite of your method would be
def method1(arg: String*): Try[List[String]] =
try {
Success(new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString))
} catch {
case e: Exception => Failure(e)
}
But of course Scala has methods for this pattern (after all that's what Try
is for), so you can write just
def method1(arg: String*): Try[List[String]] =
Try { new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString)) }
(There is a slight difference, Try { ... }
also catches some Error
s).