Skip to content

Instantly share code, notes, and snippets.

@diversit
Last active March 15, 2017 08:59
Show Gist options
  • Save diversit/c34030c016e7dbb0a556bf85880a1a69 to your computer and use it in GitHub Desktop.
Save diversit/c34030c016e7dbb0a556bf85880a1a69 to your computer and use it in GitHub Desktop.
Scala puzzler for-expression pitfall
/*
Using a for-expression (not comprehension!!) works different then expected!
When running with lists, see below, the 'println' is run 4 times as expected.
But when using Futures, the second failing Future is not 'run' and the result is still a success!
Only when 1st Future is a failure, the result is a failure.
BUT !!! In case of Future's the 'println' is NEVER run!! Why??
Note: this is tested using Twitter Futures. Don't know about Scala Future.
*/
// With Twitter Futures.
import com.twitter.util.{Future => TFuture, Await}
// Try changing Future results and see what happens.
val l1: TFuture[Int] = TFuture.value(1)
val l2: TFuture[Int] = TFuture.exception(new RuntimeException("2"))
val x = for(
_ <- l1;
_ <- l2
) {
println("here") // Is never run when using Futures!!
}
x.onFailure(_ => println("Fail"))
x.isDefined
Await.ready(x)
// This is what the for-expression is turned into.
// Now it is more clear, the second 'l2.foreach' is just not doing anything if it is a failed Future.
val r = l1.foreach { _ =>
l2.foreach { _ => () }
}
// With lists
val ll1 = List(1,2)
val ll2 = List(2,3)
val z = for(
_ <- ll1;
_ <- ll2
) {
println("here")
}
// Scala Future
import scala.concurrent.{Future => SFuture}
val sc1: SFuture[Int] = SFuture.successful(1)
val sc2: SFuture[Int] = SFuture.successful(2)
val y = for(
_ <- sc1;
_ <- sc2;
) {
println("Ok?")
""
}
// y is not a Future, but Unit !?!?!
// TFuture.foreach: TFuture[Unit], because TFuture.onSuccess: TFuture[Unit]
// SFuture.foreach: Unit , because SFuture.onSuccess: Unit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment