score:8

Accepted answer
  def craziness[a](future: future[a])(default : => a)(error: throwable)(implicit ec: executioncontext): future[a] = {
    val p = promise[a]()
    import scala.util.{success, failure, try}
    future.oncomplete {
      case _: success[_] => p.failure(error)
      case _: failure[_] => p.complete(try(default))
    }
    p.future
  }

here's a repl session showing it work:

scala> val f1 = craziness[string](future("hello!"))("my crazy default")(new throwable("boom"))
f1: scala.concurrent.future[string] = scala.concurrent.impl.promise$defaultpromise@4d154ccd

scala> f1 oncomplete { println }
failure(java.lang.throwable: boom)

scala> val f2 = craziness[string](future(throw new exception("boom!")))("my crazy default")(new throwable("boom"))
f2: scala.concurrent.future[string] = scala.concurrent.impl.promise$defaultpromise@1890516e

scala> f2 oncomplete { println }
success(my crazy default)

edit:

for completeness, def craziness[a](future: future[a]) should probably be def craziness[a](future: => future[a])

score:0

in scala 2.12 you'll be able to use transform and transformwith to make this trivial.

but until then this should get you there:

implicit class invertfuture[t](val fut: future[t]) extends anyval {
  def flip(recover: throwable => t)(fail: t => throwable)(implicit ec: executioncontext): future[t] =
        fut.recover({ case t => recover(t) }).map(t => throw fail(t))
}

// and usage:

scala> future(1).flip(_ => 2)(_ => throw new illegalstateexception("ohnoes!")) oncomplete println
failure(java.lang.illegalstateexception: ohnoes!)

score:1

i think you are after recover and recoverwith constructs. here's a quick repl session to show its usage.

$ scala
welcome to scala version 2.10.4 (java hotspot(tm) 64-bit server vm, java 1.8.0_45).
type in expressions to have them evaluated.
type :help for more information.

scala> import scala.concurrent.future
import scala.concurrent.future

scala> import scala.concurrent.executioncontext.implicits.global
import scala.concurrent.executioncontext.implicits.global

scala> val failfuture = future(sys.error("boom"))
failfuture: scala.concurrent.future[nothing] = scala.concurrent.impl.promise$defaultpromise@6e06451e

scala> val defaultvalue = 100
defaultvalue: int = 100

scala> val futurerecoveredwithdefaultfuture = failfuture.recoverwith { case e: runtimeexception => future.successful(defaultvalue) }
futurerecoveredwithdefaultfuture: scala.concurrent.future[int] = scala.concurrent.impl.promise$defaultpromise@130161f7

scala> val futurerecoveredwithdefaultvalue = failfuture.recover { case e: runtimeexception => defaultvalue }
futurerecoveredwithdefaultvalue: scala.concurrent.future[int] = scala.concurrent.impl.promise$defaultpromise@3b69e7d1

checking if this really works:

scala> import scala.concurrent.duration._
import scala.concurrent.duration._

scala> import scala.concurrent.await
import scala.concurrent.await

scala> val res1 = await.result(futurerecoveredwithdefaultfuture, 1.second)
res1: int = 100

scala> val res2 = await.result(futurerecoveredwithdefaultvalue, 1.second)
res2: int = 100

More Query from same tag