Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: ExecutionContext for future for-comprehension

When I make a future, or apply methods like onSuccess and map, I can specify ExecutionContext for them.

For example,

val f = future {
  // code
} executionContext

f.map(someFunction)(executionContext)

f onSuccess {
  // code
} executionContext

However, if I use a for-comprehension of future, how can I specify ExecutionContext for the yield part?

for {
  f <- future1
  g <- future2
} yield {
  // code to be executed after future1 onSuccess and future2 onSuccess
  // What ExecutionContext runs this code?
} // (executionContext) here does not work

And, what ExecutionContext runs the code in yield if not specified?


EDIT

OK. Thanks to answers, I found something.
If I don't define or import implicit ExecutionContext (like Implicits.global), the for-comprehension does not compile. That means, for-comprehension uses implicit ExecutionContext.

Then, how can I use for-comprehension without implicit ExecutionContext, i.e. how to specify?

like image 346
Naetmul Avatar asked Jan 21 '14 11:01

Naetmul


People also ask

How do you complete a Future in Scala?

Future represents a result of an asynchronous computation that may or may not be available yet. When we create a new Future, Scala spawns a new thread and executes its code. Once the execution is finished, the result of the computation (value or exception) will be assigned to the Future.

What is ExecutionContext in Scala?

An ExecutionContext can execute program logic asynchronously, typically but not necessarily on a thread pool. A general purpose ExecutionContext must be asynchronous in executing any Runnable that is passed into its execute -method.

What is Future object in Scala?

A Future is a placeholder object for a value that may not yet exist. Generally, the value of the Future is supplied concurrently and can subsequently be used. Composing concurrent tasks in this way tends to result in faster, asynchronous, non-blocking parallel code.

What is Future sequence in Scala?

sequence takes a list of futures and transforms it into a single future of list in an asynchronous manner. For instance, assume that you have a list of independent jobs to be run simultaneously. In such a case, the list of futures can be composed into a single future of list using Future.

Why do we need executioncontext in Scala?

Similarly to the Java Executor the Scala ExecutionContext allows to separate the business logic (i.e. what the code does) from the execution logic (i.e. how the code is executed). As a consequence one cannot just import the global execution context and get away with that. Instead we need to understand which execution context is needed and why.

How to combine multiple Scala futures into one comprehension?

By Alvin Alexander. Last updated: August 16, 2022 If you want to create multiple Scala Futures and merge their results together to get a result in a for comprehension, the correct approach is to (a) first create the futures, (b) merge their results in a for comprehension, then (c) extract the result using onComplete or a similar technique.

What is the notation for comprehensions in Scala?

For Comprehensions. Scala offers a lightweight notation for expressing sequence comprehensions. Comprehensions have the form for (enumerators) yield e, where enumerators refers to a semicolon-separated list of enumerators. An enumerator is either a generator which introduces new variables, or it is a filter.

What is the for-comprehension loop in Scala?

The Scala programming language introduced a new kind of loop: the for-comprehension. Like many other Scala constructs, the for-comprehension comes directly from Haskell. Its use goes far beyond simply looping over collections, helping us to deal with the complexity of the syntax when using a functional approach to programming.


1 Answers

The ExecutionContext parameter is actually implicit. That means you can:

import scala.concurrent.ExecutionContext

implicit val context = ExecutionContext.fromExecutor(//etc)
for {
  f <- future1
  g <- future2
} yield {
  // code to be executed after future1 onSuccess and future2 onSuccess
  // What ExecutionContext runs this code?: the one above.
}

You also have a default, namely scala.concurrent.ExecutionContext.Implicits.global. This has as many threads as the processors on the running machine.

It won't be used by all Futures by default, you still have to import it.

Update: If you really want to specifiy, although it's not recommended, you can unwrap the for yield

val combined = futureA.flatMap(x => futureB)(context)
like image 95
flavian Avatar answered Sep 22 '22 18:09

flavian