Futures and promises in Scala

Futures and promises are important abstractions in Scala for managing asynchronous and parallel computations. Futures represent a computation that may not have completed yet, while promises are used to create a future and provide a way to complete it later.

In Scala, futures are represented by the `Future` class, which provides a way to execute a block of code asynchronously and obtain a result when it becomes available. To create a future, you can use the `Future` companion object and pass a block of code to its `apply` method. For example, consider the following code that creates a future that computes the sum of a list of integers:

scala
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

val list = List(1, 2, 3, 4, 5)

val future: Future[Int] = Future {
  list.sum
}

future.foreach(result => println(s"The sum is $result"))

In this example, a new `list` of integers is defined. A new `Future` instance is then created using the `Future` companion object and a block of code that computes the sum of the list. The `foreach` method is then called on the future to register a callback function that will be called when the future completes. The callback function takes the result of the future as a parameter and prints it to the console.

Promises, on the other hand, are used to create a future and provide a way to complete it later. In Scala, promises are represented by the `Promise` class, which provides methods to complete a future with a value or an exception. For example, consider the following code that creates a promise and completes it with a value:

scala
import scala.concurrent.Promise
import scala.concurrent.ExecutionContext.Implicits.global

val promise: Promise[String] = Promise[String]()

val future: Future[String] = promise.future

future.foreach(result => println(s"Received result: $result"))

promise.success("Hello, world!")

In this example, a new `Promise` instance is created using the `Promise` companion object, and its associated future is obtained using the `future` method. The `foreach` method is then called on the future to register a callback function that will be called when the future completes. The callback function takes the result of the future as a parameter and prints it to the console.

Finally, the promise is completed with a value by calling its `success` method and passing a `String` value as a parameter. This causes the future to complete with the same value, and the callback function registered with the `foreach` method is called with the value.

Overall, futures and promises are powerful abstractions in Scala that provide a way to manage asynchronous and parallel computations. Futures represent a computation that may not have completed yet, while promises are used to create a future and provide a way to complete it later. The `scala.concurrent` package provides a set of classesand APIs for working with futures and promises, and the `ExecutionContext` trait provides a way to manage the thread pool used for executing asynchronous computations.