Created
February 9, 2019 08:14
-
-
Save LMnet/890a368c4f8c074dfaebfa26f3564fa1 to your computer and use it in GitHub Desktop.
LazyFuture example for pragmatic fp talk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package monix.eval | |
import scala.concurrent.{Await, ExecutionContext, Future} | |
import scala.concurrent.duration._ | |
object Test extends App { | |
object LazyFuture { | |
def delay[A](body: => A): LazyFuture[A] = { | |
new LazyFuture[A](ec => Future(body)(ec)) | |
} | |
def fromFuture[A](future: => Future[A]): LazyFuture[A] = { | |
new LazyFuture[A](_ => future) | |
} | |
} | |
class LazyFuture[A] private (val run: ExecutionContext => Future[A]) { self => | |
def map[B](f: A => B): LazyFuture[B] = { | |
new LazyFuture[B]((ec: ExecutionContext) => { | |
self.run(ec).map(f)(ec) | |
}) | |
} | |
def flatMap[B](f: A => LazyFuture[B]): LazyFuture[B] = { | |
new LazyFuture[B]((ec: ExecutionContext) => { | |
self.run(ec).flatMap { a => | |
f(a).run(ec) | |
}(ec) | |
}) | |
} | |
def par[B](that: LazyFuture[B]): LazyFuture[(A, B)] = { | |
new LazyFuture[(A, B)]((ec: ExecutionContext) => { | |
val selfStarted = self.run(ec) | |
val thatStarted = that.run(ec) | |
selfStarted.flatMap { selfRes => | |
thatStarted.map { thatRes => | |
(selfRes, thatRes) | |
}(ec) | |
}(ec) | |
}) | |
} | |
} | |
implicit val ec: ExecutionContext = ExecutionContext.Implicits.global | |
def future1() = Future { println(1); 1 } | |
def future2() = Future { println(2); 2 } | |
def lazyFuture1() = LazyFuture.delay { println(1); 1 } | |
def lazyFuture2() = LazyFuture.delay { println(2); 2 } | |
def futureTest: Future[Int] = { | |
for { | |
res1 <- future1() | |
res2 <- future2() | |
} yield { | |
val res = res1 + res2 | |
println(res) | |
res | |
} | |
} | |
def futureTestRtDef: Future[Int] = { | |
future1().flatMap(_ => future1()) | |
} | |
def futureTestRtVal: Future[Int] = { | |
val future = future1() | |
future.flatMap(_ => future) | |
} | |
def futureTestPar: Future[Int] = { | |
val future1val = future1() | |
val future2val = future2() | |
for { | |
res1 <- future1val | |
res2 <- future2val | |
} yield { | |
val res = res1 + res2 | |
println(res) | |
res | |
} | |
} | |
def lazyFutureTest: Future[Int] = { | |
val lazyFuture = for { | |
res1 <- lazyFuture1() | |
res2 <- lazyFuture2() | |
} yield { | |
val res = res1 + res2 | |
println(res) | |
res | |
} | |
lazyFuture.run(ec) | |
} | |
def lazyFutureTestPar: Future[Int] = { | |
val future1started = lazyFuture1() | |
val future2started = lazyFuture2() | |
val lazyFuture = for { | |
res1 <- future1started | |
res2 <- future2started | |
} yield { | |
val res = res1 + res2 | |
println(res) | |
res | |
} | |
lazyFuture.run(ec) | |
} | |
def lazyFutureTestParFixed: Future[Int] = { | |
val lazyFuture = (lazyFuture1() par lazyFuture2()).map { case (res1, res2) => | |
val res = res1 + res2 | |
println(res) | |
res | |
} | |
lazyFuture.run(ec) | |
} | |
def lazyFutureTestRtDef: Future[Int] = { | |
lazyFuture1().flatMap(_ => lazyFuture1()).run(ec) | |
} | |
def lazyFutureTestRtVal: Future[Int] = { | |
val future = lazyFuture1() | |
future.flatMap(_ => future).run(ec) | |
} | |
println("Future sequential test") | |
Await.ready(futureTest, 1.second) | |
println("Future parallel test") | |
Await.ready(futureTestPar, 1.second) | |
println("LazyFuture sequential test") | |
Await.ready(lazyFutureTest, 1.second) | |
println("LazyFuture parallel test") | |
Await.ready(lazyFutureTestPar, 1.second) | |
println("LazyFuture parallel fixed test") | |
Await.ready(lazyFutureTestParFixed, 1.second) | |
println("Future RT test def") | |
Await.ready(futureTestRtDef, 1.second) | |
println("Future RT test val") | |
Await.ready(futureTestRtVal, 1.second) | |
println("LazyFuture RT test def") | |
Await.ready(lazyFutureTestRtDef, 1.second) | |
println("LazyFuture RT test val") | |
Await.ready(lazyFutureTestRtVal, 1.second) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment