15

The following REPL snippets presume:

import scala.util.{Try, Success, Failure}

Why do these two statements not pass compilation? I get "constructor cannot be instantiated to expected type":

Failure(new Exception("a")) match {
  case Success(i) => "a"; case Failure(e) => "b"; case _ => "c"; }

Success(123) match {
  case Success(i) => "a"; case Failure(e) => "b"; case _ => "c"; }

I can get the success value out of a Try with get or toOption. Is there a corresponding way to get the failing Throwable value or Option[Throwable]?

EDIT: Casting from Failure/Success to Try works

Failure(new Exception("a")).asInstanceOf[Try[Int]] match {
  case Success(i) => "a"; case Failure(e) => "b"; case _ => "c"; }

Success(123).asInstanceOf[Try[Int]] match {
  case Success(i) => "a"; case Failure(e) => "b"; case _ => "c"; }

2 Answers 2

23

Consider this:

Try(1) match {
    case Success(i) => i
    case Failure(t) => 0 // t is the `Throwable`
}

This works because Success and Failure are sub classes of the abstract class Try. However, the following code fails to compile, because you're no longer matching on a generic Try, and instead a Failure which can never be an instance of Success.

Failure(new Exception("a")) match {
    case Success(i) => "a" // You can see it compiles if you remove this line.
    case Failure(e) => "b"
    case _ => "c"
}

This is like trying to match an Integer to a String, it doesn't really make sense.

If you want to get the Throwable via pattern matching, see the first snippet of code.

Another way you could extract the Throwable would be to use the failed method on your Try, which will wrap the Throwable from a failure within Success.

scala> val t: Throwable = Try(throw new Exception).failed.get
t: Throwable = java.lang.Exception

Calling this on a Success, however, will throw another exception.

Sign up to request clarification or add additional context in comments.

Comments

15

The first snippet doesn't compile because Success isn't a subtype of Failure. The compiler thinks you're being silly, since the Success(i) case will never match.

To take a simpler example, this also doesn't compile.

Failure(new Exception()) match { case Success(_) => }

Neither does this, for the same reason.

42 match { case Success(_) => }

What you've written does nearly work, but the value you're matching has to have a more general type of Try[_] (which it would have anyway, if the pattern match were actually being used in some useful context).

(Failure(new Exception("a")): Try[_]) match {
    case Success(i) => "a"; case Failure(e) => "b"; case _ => "c"; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.