I would like something like runProgram2 but currently that part does not compile. Is there a way to write it somewhat like runProgram2 but so it compiles..
package transformer
import scala.concurrent.{ExecutionContext, Promise, Future}
import ExecutionContext.Implicits.global
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.Duration
object TestingForComprehensions2 {
def main(args: Array[String]) = {
val future1: Future[String] = runMyProgram()
future1.onSuccess {
case r:String => System.out.println("result="+r)
}
val future2: Future[String] = runMyProgram2()
future2.onSuccess {
case r:String => System.out.println("result="+r)
}
System.out.println("waiting")
Thread.sleep(600000)
}
def runMyProgram() : Future[String] = {
val future = serviceCall()
val middle = serviceCallWrap(future)
val future2 = middle.flatMap(serviceCall2)
val future3 = future2.map(processAllReturnCodes)
future3
}
def runMyProgram2() : Future[String] = {
for {
result1 <- serviceCall()
middle = serviceCallWrap(result1)
result2 <- serviceCall2(middle)
} yield processAllReturnCodes(result2)
}
def processAllReturnCodes(theMsg: String) : String = {
"dean"+theMsg
}
def serviceCall() : Future[Int] = {
val promise = Promise.successful(5)
promise.future
}
def serviceCallWrap(f:Future[Int]) : Future[Int] = {
f
}
def serviceCall2(count:Int) : Future[String] = {
val promise = Promise.successful("hithere"+count)
promise.future
}
}
serviceCallWrap expects a future, but you are passing an Int, first step would be to remove the result1 <- serviceCall() part and call directly middle = serviceCallWrap(serviceCall()).
Now middle is a future but serviceCall2 takes an Int, in this case you can extract the value from the future using middle <- serviceCallWrap(serviceCall()), all together:
def runMyProgram2() : Future[String] = {
for {
middle <- serviceCallWrap(serviceCall())
result2 <- serviceCall2(middle)
} yield processAllReturnCodes(result2)
}
If you want to keep the comprehension structure:
def runMyProgram2() : Future[String] = {
for {
result1 <- serviceCall()
middle <- serviceCallWrap(Future(result1))
result2 <- serviceCall2(middle)
} yield processAllReturnCodes(result2)
}
The only thing you can't keep (AFAIK) is the assignment expression for middle, if you want to keep that you need to change serviceCall2 signature. This approach though has exactly the same result as the first approach, it's only more verbose.
I think I have this figured out now. or at least this compiles so I can do it on a different line.....
def runMyProgram2() : Future[String] = {
for {
result1 <- serviceCall()
middle <- serviceCallWrap(Promise.successful(result1).future)
result2 <- serviceCall2(middle)
} yield processAllReturnCodes(result2)
}
Related
How to run in parallel the two different functions that returns different datatype?
Here we have fruitFutures, and primeFutures. How can I utilize the Await.result function?
val fruits = List("apple", "orange", "mango", "banana")
val primeNums = List(2,3,5,7,11)
def executeFruit(fruit: String): Try[String] = {
Try {
s"executed $fruit"
}
}
def executePrime(prime: Int): Try[Int] = {
Try {
prime * 2
}
}
val fruitFutures: List[Future[Try[String]]] = for {
fruit <- fruits
} yield {
Future {
executeFruit(fruit)
}
}
val primeFutures: List[Future[Try[Int]]] = for {
prime <- primeNums
} yield {
Future {
executePrime(prime)
}
}
val futureResults = Await.result(Future.sequence(???), Duration.Inf)
You can try this:
val futureResults = for {
f <- Future.sequence(fruitFutures)
p <- Future.sequence(primeFutures)
} yield (f, p)
val (fruitResult, primeResult) =
Await.result(futureResults, Duration.Inf)
This will result:
List(Success(executed apple), Success(executed orange), Success(executed mango), Success(executed banana))
List(Success(4), Success(6), Success(10), Success(14), Success(22))
I want to create a function similar to the following. Basically the function, say F will create a Future say fut1. When fut1 resolves, then another Future say fut2 should get created inside fut1. The fut2 should return the final value of the function F. The code has to be non-blocking all the way. I have written something like this but the return type is not Future[Int] but Future[Future[Int]]. I understand why this is the case (because map creates a Future) but I am unable to figure out how to return Future[Int] from this code.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def fut:Future[Int] = {
val f1 = Future{ 1 } //create a Future
f1.map (x => { //when f1 finishes, create another future
println(x)
val f2 = Future{ 2 }
f2.map(x=> x) //this creates another Future and thus the return is Future[Future[Int]]
})
}
You can achieve this using flat map or for comprehension.
FlatMap-
def futureFunctionWithFlatMap: Future[Int] = {
val f1 = Future {
1
}
f1.flatMap(x => {
println(x)
val f2 = Future {
2
}
f2.map(x => x)
})
}
For Comprehension
def futureFunctionWithForComprehension: Future[Int] = {
for {
f1 <- Future { 1 }
f2 <- {
println(f1)
Future { 2 }
}
} yield f2
}
Use flatMap
val f1 = Future{ 1 } //create a Future
val f2: Future[Int] = f1.flatMap(x => {
//will be triggered only after x is ready
Future{2}
})
Is it possible to create stream of discrete events in fs2? if so how to do it.
I just started to play with the library and I know I have a lot to study. But I am not seeing any example related. e.g. I would like to create a stream for "mousemove" or "click" in scalajs or swing.
I am looking for something like in RxJS that I can use a Rx.Observable.create to create discrete events something like:
//note: pseudo code
var mouse = Rx.Observable.create( subscriber => {
document.body.addEventListener("mousemove", event =>{
subscriber.onNext(event)
})
} )
The equivalent in fs2 might not be so trivial but if anyone can suggest me how. I guess it would be using Handler and Pull/Push datatypes but I am far to understand how.
Cheers.
Here's an example I came up with which demonstrates how to use fs2 with JavaFX:
import cats.implicits._
import cats.effect._
import cats.effect.implicits._
import javafx.application.{Application, Platform}
import javafx.scene.{Node, Scene}
import javafx.scene.layout._
import javafx.stage.Stage
import fs2._
import fs2.concurrent._
import javafx.beans.value.WritableValue
import javafx.scene.control.{Label, TextField}
import javafx.scene.input.KeyEvent
import scala.concurrent.ExecutionContext
import scala.util.Try
class Fs2Ui extends Application {
override def start(primaryStage: Stage): Unit = {
implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global)
implicit val timer: Timer[IO] = IO.timer(ExecutionContext.global)
new Logic[IO]().run(primaryStage).start.unsafeRunSync()
}
class Logic[F[_]: ConcurrentEffect: ContextShift: Timer] {
import Fs2Ui._
import java.time.{Duration, Instant}
import java.util.concurrent.TimeUnit.MILLISECONDS
def run(primaryStage: Stage): F[Unit] = for {
v <- initializeUi(primaryStage)
View(input, feedback) = v
_ <- Stream(input).covary[F]
.through(typedChars)
.through(processInput)
.through(displayFeedback(feedback.textProperty))
.compile.drain
} yield ()
private def initializeUi(primaryStage: Stage): F[View] = updateUi {
val input = new TextField()
input.setPrefWidth(300)
val feedback = new Label("...")
val vbox = new VBox(input, feedback)
val root = new StackPane(vbox)
val scene = new Scene(root)
primaryStage.setScene(scene)
primaryStage.show()
View(input, feedback)
}
private def processInput: Pipe[F, TypedChar, Feedback] = for {
typed <- _
_ <- Stream.eval(ContextShift[F].shift)
res <- Stream.eval { time(processSingle(typed)) }
(d, Feedback(str)) = res
} yield Feedback(s"$str in [$d]")
private def displayFeedback(value: WritableValue[String]): Pipe[F, Feedback, Unit] =
_.map { case Feedback(str) => str } through updateValue(value)
private def time[A](f: F[A]): F[(Duration, A)] = {
val now = Timer[F].clock.monotonic(MILLISECONDS).map(Instant.ofEpochMilli)
for {
start <- now
a <- f
stop <- now
d = Duration.between(start, stop)
} yield (d, a)
}
private val processSingle: TypedChar => F[Feedback] = {
import scala.util.Random
import scala.concurrent.duration._
val prng = new Random()
def randomDelay: F[Unit] = Timer[F].sleep { (250 + prng.nextInt(750)).millis }
c => randomDelay *> Sync[F].delay(Feedback(s"processed $c"))
}
}
}
object Fs2Ui {
case class View(input: TextField, feedback: Label)
case class TypedChar(value: String)
case class Feedback(value: String)
private def typedChars[F[_]: ConcurrentEffect]: Pipe[F, Node, TypedChar] = for {
node <- _
q <- Stream.eval(Queue.unbounded[F, KeyEvent])
_ <- Stream.eval(Sync[F].delay {
node.setOnKeyTyped { evt => (q enqueue1 evt).toIO.unsafeRunSync() }
})
keyEvent <- q.dequeue
} yield TypedChar(keyEvent.getCharacter)
private def updateValue[F[_]: Async, A](value: WritableValue[A]): Pipe[F, A, Unit] = for {
a <- _
_ <- Stream.eval(updateUi(value setValue a))
} yield ()
private def updateUi[F[_]: Async, A](action: => A): F[A] =
Async[F].async[A] { cb =>
Platform.runLater { () =>
cb(Try(action).toEither)
}
}
}
The specific parts that demonstrate bindings between fs2 and JavaFX are the two Pipes: typedChars and updateValue. Personally, I think, the most challenging part was adapting a KeyEvent listener to look like an fs2 Stream of events:
node.setOnKeyTyped { evt => (q enqueue1 evt).toIO.unsafeRunSync() }
In the code below I have to return the result of a future that is invoked after another future. I'm getting the following error in the future2.map line:
type mismatch; found : scala.concurrent.Future[play.api.mvc.Result]
required: play.api.mvc.Result
How to make this work?
def method1 = Action.async { request =>
val future1 = f1
future1.map { result1 =>
val future2 = f2
future2.map { result2 =>
Ok(result1+result2+"")
}
}
}
def f1 = Future { 1 }
def f2 = Future { 2 }
You could do this in many ways. But first, you need to understand how map and flatMap work with Future:
def map[S](f: (T) ⇒ S): Future[S]
def map[S](f: (T) ⇒ Future[S]): Future[Future[S]]
def flatMap[S](f: (T) ⇒ Future[S]): Future[S]
Note that,in above signatures, you are calling map and flatMap with a value that already is a future i.e Future[<some-value>].map(...) or Future[<some-value>].flatMap(...).
Approach 1:
def method1 = Action.async { request =>
val future1 = f1
future1.flatMap { result1 => //replaced map with flatMap
val future2 = f2
future2.map { result2 =>
Ok(result1+result2+"")
}
}
}
def f1 = Future { 1 }
def f2 = Future { 2 }
Approach 2:
def method1 = Action.async { request =>
val future1 = f1
future1.flatMap { result1 => //replaced map with flatMap
val future2 = f2
future2.flatMap { result2 => //replaced map with flatMap
Future.successful{Ok(result1+result2+"")} // used Future.successful{} to generate a Future of Result
}
}
}
def f1 = Future { 1 }
def f2 = Future { 2 }
Changing future1.map to future1.flatMap should do the trick. Mapping over a Future returns another Future and changes the value inside. In this case, you're returning a Future that contains another Future that contains a Result. By using flatMap, it essentially flattens the nested Future[Future[Result]] into a Future[Result].
I'm creating an async library using Scala 2.10 futures. The constructor for the library takes a sequence of user-defined objects that implement a certain trait, and then a method on the library class sends some data one-by-one into the user-defined objects. I want the user to provide the ExecutionContext for the async operations when setting up the main instance, and then for that context to get passed into the user-defined objects as necessary. Simplified (pseudo?)code:
case class Response(thing: String)
class LibraryObject(stack: Seq[Processor])(implicit context: ExecutionContext) {
def entryPoint(data: String): Future[Response] = {
val response = Future(Response(""))
stack.foldLeft(response) { (resp, proc) => proc.process(data, resp) }
}
}
trait Processor {
def process(data: String, resp: Future[Response]): Future[Response]
}
It might be used something like this:
class ThingProcessor extends Processor {
override def process(data: String, response: Future[Response]) = {
response map { _.copy(thing = "THE THING") }
}
}
class PassThroughProcessor extends Processor {
override def process(request: Request, response: Future[Response]) = {
response
}
}
object TheApp extends App {
import ExecutionContext.Implicits.global
val stack = List(
new ThingProcessor,
new PassThroughProcessor
)
val libObj = new LibraryObject(stack)
val futureResponse = libObj.entryPoint("http://some/url")
// ...
}
I get a compile error for ThingProcessor:
Cannot find an implicit ExecutionContext, either require one yourself or import ExecutionContext.Implicits.global
My question is, how do I implicitly supply the ExecutionContext that LibraryObject has to the user-defined objects (ThingProcessor and PassThroughProcessor) or their methods without making the user (who will be writing the classes) worry about it--that is to say, I would prefer that the user did not have to type:
class MyFirstProcessor(implicit context: ExecutionContext)
or
override def process(...)(implicit context: ExecutionContext) = { ... }
The implicit scope includes companion objects and type parameters of base classes.
Or, library.submit(new library.Processor { def process() ... }).
This works, but wasn't my first thought, which was to be more clever:
import concurrent._
import concurrent.duration._
class Library(implicit xc: ExecutionContext = ExecutionContext.global) {
trait Processor {
implicit val myxc: ExecutionContext = xc
def process(i: Future[Int]): Future[Int]
}
def submit(p: Processor) = p process future(7)
}
object Test extends App {
val library = new Library
val p = new library.Processor {
def process(i: Future[Int]) = for (x <- i) yield 2 * x
}
val res = library submit p
val z = Await result (res, 10.seconds)
Console println z
}
Update:
import concurrent._
import concurrent.duration._
import java.util.concurrent.Executors
class Library()(implicit xc: ExecutionContext = ExecutionContext.global) {
trait Processor {
implicit val myxc: ExecutionContext = xc
def process(i: Future[Int]): Future[Int]
}
def submit(p: Processor) = p process future(7)
}
object ctx {
val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor
}
object library1 extends Library
object library2 extends Library()(ctx.xc)
object p extends library1.Processor {
def process(i: Future[Int]) = for (x <- i) yield 2 * x
}
object q extends library2.Processor {
def process(i: Future[Int]) = for (x <- i) yield 3 * x
}
object Test extends App {
val res = library1 submit p
//val oops = library2 submit p
//val oops = library1 submit q
val z = Await result (res, 10.seconds)
Console println z
Console println (Await result (library2 submit q, 10.seconds))
ctx.xc.shutdownNow()
}
It isn't much of a stretch to:
class Library(implicit xc: ExecutionContext = ExecutionContext.global) {
def submit(p: Processor): Future[Int] = p dueProcess future(7)
}
trait Processor {
implicit var myxc: ExecutionContext = _
def dueProcess(i: Future[Int])(implicit xc: ExecutionContext) = {
myxc = xc
process(i)
}
protected def process(i: Future[Int]): Future[Int]
}
object ctx {
val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor
}
object Test extends App {
def db() = Console println (new Throwable().getStackTrace mkString ("TRACE [\n ", "\n ", "\n]"))
val library = new Library()(ctx.xc)
val p = new Processor {
protected def process(i: Future[Int]) = for (x <- i) yield { db(); 2 * x }
}
val res = library submit p
val z = Await result (res, 10.seconds)
Console println z
ctx.xc.shutdownNow()
}