Skip to content

Instantly share code, notes, and snippets.

@sam
Last active December 13, 2015 17:09
Show Gist options
  • Save sam/4945452 to your computer and use it in GitHub Desktop.
Save sam/4945452 to your computer and use it in GitHub Desktop.
import concurrent._
import ExecutionContext.Implicits.global
// Sleep each for 10 seconds:
for {
result1 <- future { Thread.sleep(10000); 1 }
result2 <- future { Thread.sleep(10000); 2 }
} println(s"result1 -> $result1, result2 -> $result2")
// So that took about 20 seconds. for-comprehensions are a way to flatten loops.
// Each additional binding is an inner loop. To demonstrate:
for {
outer <- 1 to 10
inner <- 1 to 10
} yield s"$outer:$inner"
// What we want is parallel operation. Use Future.zip instead:
val result1 = future { Thread.sleep(10000); 1 }
val result2 = future { Thread.sleep(10000); 2 }
result1 zip result2 map {
case (r1, r2) => println(s"result1 -> $r1, result2 -> $r2")
}
// And you'll see the println in about 10 seconds now.
// Try pasting the two vals above into your REPL first. Count to 5. Then paste the zip -> map.
// Your output should print in about 5 seconds now. The futures start processing when they're
// defined. Not when you attempt to map the results. Makes sense right? If you want a database
// result, you want that thing to go off and start work immediately. Not wait until you actually
// need the results to print. Nice to see it in action though.
// You might guess at this point that the important thing is to make the call to the future to
// get it going. So you defined the vals above, you could still use a for-comprehension at this
// point and get mostly the same behavior:
for(r1 <- result1; r2 <- result2) println(s"result1 -> $r1, result2 -> $r2")
// Yes, it's calling flatMap on the first one, then chaining the second, but since our RHS values
// are Futures and not Collections, that doesn't matter a whole lot. The above is _almost_
// equivilent to the following:
result1.flatMap { r1 => result2.map { r2 => println(s"result1 -> $r1, result2 -> $r2") } }
// A bit ugly though right? That's the point of for-comprehensions. Prettifying nested mapping.
// I said "almost", because the above returns the value (Future[Unit]). Our for-comprehension
// would do the same if we had written it with a yield:
for(r1 <- result1; r2 <- result2) yield println(s"result1 -> $r1, result2 -> $r2")
// Since we didn't care about the return value of println (which is Unit aka void), we just
// ignored it is all.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment