Skip to content

Instantly share code, notes, and snippets.

@missingfaktor
Last active August 29, 2015 14:17
Show Gist options
  • Select an option

  • Save missingfaktor/c82d211d2074cbb38231 to your computer and use it in GitHub Desktop.

Select an option

Save missingfaktor/c82d211d2074cbb38231 to your computer and use it in GitHub Desktop.
def foo(): Future[Bob] = {
  if (flag) 
    someAsyncCall()
  else
    throw new RuntimeException()
}

In the above code, the exception was thrown outside a future, so it'll never reach a handle/rescue block that was defined somewhere up the call stack. The type here didn't prevent us from doing it because exceptions are an effect not seen by the type system.

If the effect was checked, we'd have something like:

def foo(): Future[Bob @throws[RuntimeException]] = ...

In this case, the above code would have failed to compile with something like:

Expected  : Future[Bob @throws[RuntimeException]]
But Found : Future[Bob] @throws[RuntimeException]

With regular values, you'd have Future[Try[A]] and Try[Future[A]] that are two different things. So you can't possibly do:

def foo(): Future[Try[Bob]] = {
  if (flag)
    someAsyncCall()
  else
    Failure(Future.exception(new RuntimeException))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment