Why do we need both Future and Promise?
Asked Answered
I

3

5

As I know, Future is read-only and Promise is write-once data structure.

We need a Promise to complete a Future

For example,

object Lie extends Throwable

val lie = Future { throw Lie } 

val guess = Promise[String]()     

lie.onComplete { case Success(s) => guess.success("I knew it was true!") 
                 case Failure(t) => guess.failure("I knew it was lie")} 
// return type: Unit 

guess.future.map(println) 
// res12: scala.concurrent.Future[Unit] = List()
// I knew it was lie!
// Requires Promise to chain Future with exception 


But, I can't understand why we need to have both Future and Promise

I guess Promise is required because of Future.onComplete signature

Since Future.onComplete return type is Unit,Future with possible exceptions cannot be chained

I assume Promise was introduced to overcome this limitation


But why not just change the signature of Future.onComplete ?

Changing the return type of Future.onComplete as Future[T] will enable chaining on Future with exception

and then, Future does not need Promise

For example, code above can be changed into

val lie = Future { throw Lie } 

lie.onComplete { 
   case Success(s) => "I knew it was true!"
   case Failure(t) => "I knew it was lie!"
}.map(println) 

//onComplete return type is Future[String]


My question is

1) am I right? does Future not need Promise , If onComplete signature is changed from Unit to Future[T]?

2) Why Future and Promise are divided in the first place ?

UDPATE

Thanks to the repliers, Now I understand the purpose of Promise. It wasn't actually for Future chaining

If I may, can I ask you

Why onComplete returns Unit ??

It can actually return Future[T] to enable chaining Future easily

For example

Future { throw Error }.onComplete {
  case Success(s) => "Success" 
  case Failure(t) => throw Error
}.onComplete {
  case Success(s) => "Success"
  case Failure(t) => throw Error 
}. ... 
Inamorato answered 30/10, 2016 at 17:26 Comment(3)
(regarding your UPDATE); you probably want the transform method that's new in 2.12, see here: github.com/viktorklang/blog/blob/master/… (the other articles in this "blog" are also worth reading)Catechism
@Fabian thanks Fabian, This is the best answer to meInamorato
Unfortunately Java 8's authors concluded we don't need to separate the two concepts (aka CompletableFuture).Coattail
K
2

am I right? does Future not need Promise , If onComplete signature is changed from Unit to Future[T]?

You're mixing things up a little. Let's clarify.

A Future[T] represents a computation which will complete in the future. That is, you pass Future.apply a function which will execute on a thread assigned by some ExecutionContext you define.

Now, on the other hand, a Promise[T] is a way to create a Future[T], without actually creating a Future[T]. A good example for this would be the Future.successful method (which will internally consume Promise.successful):

def successful[T](result: T): Future[T] = Promise.successful(result).future

This requires no ExecutionContext and no queuing if any additional resources. It's merely a convenience wrapper that allows you to "artificially" create a Future[T].

Katharynkathe answered 30/10, 2016 at 17:47 Comment(4)
Thanks for your explanation, it helps me to understand better.Inamorato
Kinda funny. "This requires no ExecutionContext and no queuing if any additional resources. It's merely a convenience wrapper that allows you to "artificially" create a Future[T]." Well because to produce result you had to use a thread. Now when it's completed, you show us how to use the redundant Promise API in order to wrap result in an already completed Future. This by no means a good reason to have both Promise and Future APIs. Promise may have been okay to remain as an internal implementation detail, but I don't see any reason for it to be exposed to the developer.Threegaited
@Threegaited Lets assume you had some code which wraps some native code. This function does some some work, perhaps asynchronously using some C thread, and you wanted to pass it some void* to invoke when completed (some arbitrary handler). A Promise would allow you to defer control of the completion to that code, since only it knows when the operation completes.Katharynkathe
@YuvalItzchakov I am not sure I got your idea right - and I was only referring to the OP question in the Scala environment - but it looks to me like what you are trying to do can (also) be done by Future.onComplete. BTW I think the Promise itself does not know WHEN the operation completes (onComplete), it only knows IF it was completed (isCompleted). The definition of Promise you gave is good. I think a clearer definition would be: "Promise is a factory of a Future." But it's confusing that the Promise is often completed (i.e. updated) by another Future.Threegaited
C
7

Future.apply[T](block: => T): Future[T] is syntactic sugar for Future.unit.map(_ => block)[1]

A Future represents a value which may or may not be currently available.

A Promise represents the obligation to provide such a value at some point.

Having separate entities for Future (for reads) and Promise (for writes) means that it is easy to reason about capabilities:

  • When a Future is a parameter, it is a request to have some value at some point and when it is used as a return type, it's a response which may not be currently available.

  • When a Promise is a parameter, it is the "consumption" of responsibility of producing some value at some point, and when it is used as a return type it is the "production" of responsibility to produce the value at some point.

All in all, being able to reason about capabilities, especially in asynchronous, or even concurrent programs, is extremely valuable.

Most of the time Promises need not be used, since that is transparently handled by the Future-combinators—but when integrating with third party software or networking libraries it can be extremely useful.

For more information about interesting new features in Scala 2.12, have a look here.

1: Where Future.unit is defined as: val unit: Future[Unit] = Future.successful(())

Compensatory answered 31/10, 2016 at 12:2 Comment(2)
Thanks a lot. Your answer is very helpful! But what is the Future.unit?? It is not explained in api docsInamorato
@wonpyoPark That's explained in the footnote. For more info, look at the link to the more news in scala 2.12 in my answer.Compensatory
K
2

am I right? does Future not need Promise , If onComplete signature is changed from Unit to Future[T]?

You're mixing things up a little. Let's clarify.

A Future[T] represents a computation which will complete in the future. That is, you pass Future.apply a function which will execute on a thread assigned by some ExecutionContext you define.

Now, on the other hand, a Promise[T] is a way to create a Future[T], without actually creating a Future[T]. A good example for this would be the Future.successful method (which will internally consume Promise.successful):

def successful[T](result: T): Future[T] = Promise.successful(result).future

This requires no ExecutionContext and no queuing if any additional resources. It's merely a convenience wrapper that allows you to "artificially" create a Future[T].

Katharynkathe answered 30/10, 2016 at 17:47 Comment(4)
Thanks for your explanation, it helps me to understand better.Inamorato
Kinda funny. "This requires no ExecutionContext and no queuing if any additional resources. It's merely a convenience wrapper that allows you to "artificially" create a Future[T]." Well because to produce result you had to use a thread. Now when it's completed, you show us how to use the redundant Promise API in order to wrap result in an already completed Future. This by no means a good reason to have both Promise and Future APIs. Promise may have been okay to remain as an internal implementation detail, but I don't see any reason for it to be exposed to the developer.Threegaited
@Threegaited Lets assume you had some code which wraps some native code. This function does some some work, perhaps asynchronously using some C thread, and you wanted to pass it some void* to invoke when completed (some arbitrary handler). A Promise would allow you to defer control of the completion to that code, since only it knows when the operation completes.Katharynkathe
@YuvalItzchakov I am not sure I got your idea right - and I was only referring to the OP question in the Scala environment - but it looks to me like what you are trying to do can (also) be done by Future.onComplete. BTW I think the Promise itself does not know WHEN the operation completes (onComplete), it only knows IF it was completed (isCompleted). The definition of Promise you gave is good. I think a clearer definition would be: "Promise is a factory of a Future." But it's confusing that the Promise is often completed (i.e. updated) by another Future.Threegaited
R
1

No.

Futurecannot cover the use cases of Promise. Promise has its own value. You cannot replace Future with Promise.

Future represents a computation which is available at a later point of time. You can get the result using onComplete once the future execution is complete and you can compose futures using map, flatMap, recover and recoverWith.

Promise is one time write container, clients can subscribe to the container. When subscribed client gets a future to wait until value is written into that container called promise.

Future is read-only

You cannot use future as one time write container. You can only read from future.

But Promise is different.

What if you want to give user something, which you do not have right now but you think you will have it soon ?

That means you are promising user something which you do not have right now.

So you want to keep the user waiting till you have the thing which you will give it to user. Thats when you do p.future and generate a future so that user can wait for the result using the future.

Once you have the result which you promised to give the user, You give to user by making the future a success or failure when something bad happens (i.e by doing p.complete).

Even if onComplete return type is changed to Future[T]. Future cannot act like or serve purpose of Promise.

Creating future using Future companion object

Future can be created by using Future.apply also. In this case future created would be complete once the computation inside the future finishes.

Future is used to subscribe to the result of the time-consuming computation, whereas Promise can be a publish and subscribe model.

Romine answered 30/10, 2016 at 17:41 Comment(16)
thank you for answer, did you read my question after I edited ? can you be more specific to my question about onComplete signature (return type)Inamorato
@WonpyoPark. Even if onComplete return type is changed to Future[T]. Future cannot act like or serve purpose of Promise.Romine
Thanks a lot! Thanks to you, I understand purpose of PromiseInamorato
@pamu You did not explain what you can do only with Promise but not with Future. You seemed to be promising an explanation but there was none coming.Threegaited
@Threegaited added it now.Romine
@pamu It is not clear what you try to say. Is it clear to you? First, clients are not normally supposed to have access to the Promise. They should only access the Future. It is the task implementer who uses the Promise to update its status with either Success or Failure, when the task completes. Second, I ask why do we need to expose Promise to the developer? Future will update its status anyway to success/failure when it completes, even if I as a developer know nothing about Promise (although internally it's done by updating the corresponding Promise).Threegaited
@Threegaited try to use promise api and you will understand what I want to say.Romine
@Threegaited client get future creating from promise.future and this future will complete when a value is written into promise.Romine
@Threegaited Future created by promise.future will never complete if a value is not written into the promise. There is no harm in clients accessing the promise.Romine
@Threegaited Please use the promise api and everything will be clearRomine
@pamu "Future created by promise.future will never complete if a value is not written into the promise." Yes but who told you to create a Future by promise.future? You can create it by Future.apply. "There is no harm in clients accessing the promise." You really want to let clients tell the server when a task is completed?!?!?Threegaited
@Threegaited 1) I have written in the answer that future is being created by using promise.future 2) clients can access the promise meaning to the extent it is permissible by the domain. There are things that you have to infer from the answer. If you want to improve the answer please go ahead and edit. If not write ur own answer. I am not here to argue nitty gritty details.Romine
@pamu and I have written that this does not prove that Promise is essential, since Future can be created by Future.apply.Threegaited
@pamu All good but you have not shown that "Future cannot cover the use cases of Promise. Promise has its own value. You cannot replace Future with Promise." What you did is called Hand-waving.Threegaited
@Threegaited "Future is read-only. You cannot use future as one time write container. You can only read from future."Romine
@Threegaited "Future is used to subscribe to the result of the time-consuming computation, whereas Promise can be a publish and subscribe model."Romine

© 2022 - 2024 — McMap. All rights reserved.