Advertisement
Guest User

Untitled

a guest
Sep 30th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.84 KB | None | 0 0
  1. import scala.concurrent.{ExecutionContext, Future}
  2.  
  3. /**
  4. * Takes care of computations
  5. *
  6. * Success(either) - the computation will be continued.
  7. * Failure(error) - the computation was failed with unhandled error.
  8. *
  9. * Either[Result, T]:
  10. * Left(result) is a final and handled result, another computations (map, flatMap) will be ignored.
  11. * Right(T) is a current result. Functions in map/flatMap will continue the computation.
  12. *
  13. * Example:
  14. * {{{
  15. * import scala.concurrent.ExecutionContext.Implicits.global
  16. * import scala.concurrent.{ExecutionContext, Future}
  17. * import com.drivergrp.rep.server.utils.Computation
  18. *
  19. * def successful = for {
  20. * x <- Computation.continue(1)
  21. * y <- Computation.continue(2)
  22. * } yield s"$x + $y"
  23. *
  24. * // Prints "Success(1 + 2)"
  25. * successful.join.onComplete(println)
  26. *
  27. * def failed = for {
  28. * x <- Computation.abort("Failed on x")
  29. * _ = println("Second step")
  30. * y <- Computation.continue(2)
  31. * } yield s"$x + $y"
  32. *
  33. * // Prints "Success(Failed on x)"
  34. * failed.join.onComplete(println)
  35. * }}}
  36. *
  37. * @param future The final flow in a future.
  38. * @tparam R Type of result for aborted computation.
  39. * @tparam T Type of result for continued computation.
  40. */
  41. final case class Computation[+R, +T](future: Future[Either[R, T]]) {
  42.  
  43. def flatMap[R2, T2](f: T => Computation[R2, T2])(implicit ec: ExecutionContext, ev: R <:< R2): Computation[R2, T2] = {
  44. Computation(future.flatMap {
  45. case Left(x) => Future.successful(Left(x))
  46. case Right(x) => f(x).future
  47. })
  48. }
  49.  
  50. def map[T2](f: T => T2)(implicit ec: ExecutionContext): Computation[R, T2] = flatMap { a =>
  51. Computation.continue(f(a))
  52. }
  53.  
  54. def filter(f: T => Boolean)(implicit ec: ExecutionContext): Computation[R, T] = map { a =>
  55. if (f(a)) a
  56. else throw new NoSuchElementException("When filtering")
  57. }
  58.  
  59. def withFilter(f: T => Boolean)(implicit ec: ExecutionContext): Computation[R, T] = filter(f)
  60.  
  61. def foreach[T2](f: T => T2)(implicit ec: ExecutionContext): Unit = future.foreach {
  62. case Right(x) => f(x)
  63. case _ =>
  64. }
  65.  
  66. def toFuture[R2](resultFormatter: T => R2)(implicit ec: ExecutionContext, ev: R <:< R2): Future[R2] = future.map {
  67. case Left(x) => x
  68. case Right(x) => resultFormatter(x)
  69. }
  70.  
  71. def toFuture[R2](implicit ec: ExecutionContext, ev1: R <:< R2, ev2: T <:< R2): Future[R2] = future.map {
  72. case Left(x) => x
  73. case Right(x) => x
  74. }
  75.  
  76. }
  77.  
  78. object Computation {
  79.  
  80. def continue[T](x: T): Computation[Nothing, T] = Computation(Future.successful(Right(x)))
  81.  
  82. def abort[R](result: R): Computation[R, Nothing] = Computation(Future.successful(Left(result)))
  83.  
  84. def fail(exception: Throwable): Computation[Nothing, Nothing] = Computation(Future.failed(exception))
  85.  
  86. def fromFuture[T](input: Future[T])(implicit ec: ExecutionContext): Computation[Nothing, T] = Computation {
  87. input.map { x => Right(x) }
  88. }
  89.  
  90. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement