Skip to content

Instantly share code, notes, and snippets.

@sam
Created October 11, 2013 20:43
Show Gist options
  • Save sam/6941737 to your computer and use it in GitHub Desktop.
Save sam/6941737 to your computer and use it in GitHub Desktop.
Makes mapping lots of futures pretty/easy.
// Imagine you have a lot of futures. You don't want to make them synchronous with a for-comprehension, so you want to zip them.
// Unfortunately you'll get nested tuples from that, and if you have more than two, that gets ugly quick.
// ScalaZ has a solution with the |@| operator, but it's more general and seems to really torture the compiler.
// This is an alternative for this specific scenario (zip several async Futures together and map them), and is much faster
// (in IntelliJ at least).
import my.api
import TupleFutureUnzip._
(ChanneledPresenter.tree, api.photos.all) unzip(new PhotosPresenter(_, _))
// That's just two arguments, but doesn't matter how many (I've provided the first 8 at least for you).
// You can also pattern-match since it's just a map:
(ChanneledPresenter.tree, api.pages.getByRoute(route)) unzip {
case (tree, Some(page)) => Some(new PagePresenter(tree, page))
case _ => None
}
// Hope you find this helpful!
package util
import scala.concurrent.{ExecutionContext, Future}
object TupleFutureUnzip {
type Tuple1Futures[A] = Tuple1[Future[A]]
type Tuple2Futures[A,B] = Tuple2[Future[A],Future[B]]
type Tuple3Futures[A,B,C] = Tuple3[Future[A],Future[B],Future[C]]
type Tuple4Futures[A,B,C,D] = Tuple4[Future[A],Future[B],Future[C],Future[D]]
type Tuple5Futures[A,B,C,D,E] = Tuple5[Future[A],Future[B],Future[C],Future[D],Future[E]]
type Tuple6Futures[A,B,C,D,E,F] = Tuple6[Future[A],Future[B],Future[C],Future[D],Future[E],Future[F]]
type Tuple7Futures[A,B,C,D,E,F,G] = Tuple7[Future[A],Future[B],Future[C],Future[D],Future[E],Future[F],Future[G]]
type Tuple8Futures[A,B,C,D,E,F,G,H] = Tuple8[Future[A],Future[B],Future[C],Future[D],Future[E],Future[F],Future[G],Future[H]]
implicit class Tuple1Unzip[A](val self: Tuple1Futures[A]) extends AnyVal {
def unzip[R](fun: Function1[A,R])(implicit ec: ExecutionContext): Future[R] = {
self._1 map { fun(_) }
}
}
implicit class Tuple2Unzip[A,B](val self: Tuple2Futures[A,B]) extends AnyVal {
def unzip[R](fun: Function2[A,B,R])(implicit ec: ExecutionContext): Future[R] = {
self._1 zip self._2 map {
case (a, b) => fun(a,b)
}
}
}
implicit class Tuple3Unzip[A,B,C](val self: Tuple3Futures[A,B,C]) extends AnyVal {
def unzip[R](fun: Function3[A,B,C,R])(implicit ec: ExecutionContext): Future[R] = {
self._1 zip self._2 zip self._3 map {
case ((a, b), c) => fun(a,b,c)
}
}
}
implicit class Tuple4Unzip[A,B,C,D](val self: Tuple4Futures[A,B,C,D]) extends AnyVal {
def unzip[R](fun: Function4[A,B,C,D,R])(implicit ec: ExecutionContext): Future[R] = {
self._1 zip self._2 zip self._3 zip self._4 map {
case (((a, b), c), d) => fun(a,b,c,d)
}
}
}
implicit class Tuple5Unzip[A,B,C,D,E](val self: Tuple5Futures[A,B,C,D,E]) extends AnyVal {
def unzip[R](fun: Function5[A,B,C,D,E,R])(implicit ec: ExecutionContext): Future[R] = {
self._1 zip self._2 zip self._3 zip self._4 zip self._5 map {
case ((((a, b), c), d), e) => fun(a,b,c,d,e)
}
}
}
implicit class Tuple6Unzip[A,B,C,D,E,F](val self: Tuple6Futures[A,B,C,D,E,F]) extends AnyVal {
def unzip[R](fun: Function6[A,B,C,D,E,F,R])(implicit ec: ExecutionContext): Future[R] = {
self._1 zip self._2 zip self._3 zip self._4 zip self._5 zip self._6 map {
case (((((a, b), c), d), e), f) => fun(a,b,c,d,e,f)
}
}
}
implicit class Tuple7Unzip[A,B,C,D,E,F,G](val self: Tuple7Futures[A,B,C,D,E,F,G]) extends AnyVal {
def unzip[R](fun: Function7[A,B,C,D,E,F,G,R])(implicit ec: ExecutionContext): Future[R] = {
self._1 zip self._2 zip self._3 zip self._4 zip self._5 zip self._6 zip self._7 map {
case ((((((a, b), c), d), e), f), g) => fun(a,b,c,d,e,f,g)
}
}
}
implicit class Tuple8Unzip[A,B,C,D,E,F,G,H](val self: Tuple8Futures[A,B,C,D,E,F,G,H]) extends AnyVal {
def unzip[R](fun: Function8[A,B,C,D,E,F,G,H,R])(implicit ec: ExecutionContext): Future[R] = {
self._1 zip self._2 zip self._3 zip self._4 zip self._5 zip self._6 zip self._7 zip self._8 map {
case (((((((a, b), c), d), e), f), g), h) => fun(a,b,c,d,e,f,g,h)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment