Differences between Future[Try[T]] and Try[Future[T]]

閲覧: 2,346 回
最初の未読メッセージにスキップ

Deryk Lyu

未読、
2014/01/05 16:51:522014/01/05
To: scala...@googlegroups.com
Hi all,
I got very confused by the stacked expression of future and try.

So what are the differences between Future[Try[T]] and Try[Future[T]]?
How to use them in a For-comprehension?

1: ft: Future[Try[T]]:
for {tempfuture <-ft 
      temp <-tempfuture} yield temp 

2: tf: Try[Future[T]]:
for {temptry <- tf 
      temp <-temptry} yield temp 

Are the above two usages correct?

Thanks.
Deryk

Erik Osheim

未読、
2014/01/05 17:16:292014/01/05
To: Deryk Lyu、scala...@googlegroups.com
On Sun, Jan 05, 2014 at 01:51:52PM -0800, Deryk Lyu wrote:
> Hi all,
> I got very confused by the stacked expression of future and try.
>
> So what are the differences between Future[Try[T]] and Try[Future[T]]?

Your for-comprehensions looked correct to me (they are both basically
the same). You should be aware that as written, they have no effect,
since the resulting type of the comprehension will be the same as the
starting value.

The difference between these two types is that Try[Future[T]] will
either fail now, or return a future that is guaranteed to produce a
value of T.

On the other hand, Future[Try[T]] is a future that is guaranteed to
produce a value of Try[T], but the value will either be Success(t) or
Failure(exception).

Hope this helps!

-- Erik

Deryk Lyu

未読、
2014/01/06 23:32:362014/01/06
To: scala...@googlegroups.com、Deryk Lyu、er...@plastic-idolatry.com
Thanks, Erik.
Now I understand Future[Try[T]]. But I am still confused about Try[Future[T]].

Try[Future[T]] will either fail now, or return a future that is guaranteed to produce a value of T. 
Future[T] may be a success or a failure. So 
if Future[T]  is a success, then what is Try[SuccessofFuture]?
if Future[T] is a failure, then what is Try[FailureofFuture]?

Thanks
Deryk

Constantine

未読、
2014/01/07 1:21:172014/01/07
To: scala...@googlegroups.com、Deryk Lyu、er...@plastic-idolatry.com
The differece is quite simple:

"Try" is an value that describes outcome of some asynchronous process. "Future" is live status of some asynchronous process (it might be in progress or finished with some outcome)

So Future[Try[T]] represents some process that will produce an outcome value, possibly from other process. This might be useful, if an exception is also a possible value and it should be processed rather than fail the entire process.

Try[Future[T]] is an outcome of some process that produces a Future object, it possibly had a status Future[Future[T]]. This usually useless, since the status could have been just Future[T].

Best Regards,
Constantine Plotnikov

вторник, 7 января 2014 г., 8:32:36 UTC+4 пользователь Deryk Lyu написал:

Deryk Lyu

未読、
2014/01/07 2:35:462014/01/07
To: scala...@googlegroups.com、Deryk Lyu、er...@plastic-idolatry.com


This might be useful, if an exception is also a possible value and it should be processed rather than fail the entire process.
Would you like to elaborate this? What do you mean by "it should be processed"? 

Thanks
Deryk

Constantine

未読、
2014/01/07 4:25:282014/01/07
To: scala...@googlegroups.com、Deryk Lyu、er...@plastic-idolatry.com
The better example would be Future[Map[X,Try[T]]].

For example, lets us have a list of URL that we want to download. We submit them to some service like:

def download(urls : List[URL]) : Future[Map[URL, Array[Byte]]]

If service is done in this way, if one download fails, the entire process fails. The better interface would be:

def download(urls : List[URL]) : Future[Map[URL, Try[Array[Byte]]]]

In that case we will recieve data for downloaded files and failure for failed files. The failed files could 
be resubmitted, or user could be notified.

The method "def download(url : URL)  : Future[Try[Array[Byte]]]" could be inside implementation 
for passing to some general distributed evaluation service.

Best Regards,
Constantine Plotnikov

вторник, 7 января 2014 г., 11:35:46 UTC+4 пользователь Deryk Lyu написал:

Deryk Lyu

未読、
2014/01/08 10:58:492014/01/08
To: scala...@googlegroups.com、Deryk Lyu、er...@plastic-idolatry.com
def download(urls : List[URL]) : Future[Map[URL, Array[Byte]]]
If service is done in this way, if one download fails, the entire process fails.

Do you mean If one download fails, Map[URL, Array[Byte]] will fail because Array[Byte] is empty?

So similarly, with Future[Map[URL, Try[Array[Byte]]]], the empty Array[Byte] can be captured in "Try"?

Thanks
Deryk

Constantine Plotnikov

未読、
2014/01/09 6:46:542014/01/09
To: Deryk Lyu、scala-user
The problem is not array is empty, but because there was failure that has data that need to be processed. The empty array is a valid response, as web resource could be just empty. Null instead of array does not give a reason for failure, the user will not have information that allow one to fix the problem.

However, Try value will contain either value or failure in the case when value failed to be produced.

Best Regards,
Constantine Plotnikov


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Deryk Lyu

未読、
2014/01/13 14:34:092014/01/13
To: Constantine Plotnikov、scala-user
Hi Constantine,
What exactly is the case Future[Try[T]] is useful?
Would you mind showing me an example? I am still struggling to understand what you said. But failed...


Thanks
Deryk

√iktor Ҡlang

未読、
2014/01/13 14:42:062014/01/13
To: Deryk Lyu、Constantine Plotnikov、scala-user
A Future has-a Try:

abstract defonComplete[U](func: (Try[T]) ⇒ U)(implicit executor: ExecutionContext)Unit

When this future is completed, either through an exception, or a value, apply the provided function.

--
Cheers,

Viktor Klang

Concurrent, Distributed

Twitter: @viktorklang

Kevin Wright

未読、
2014/01/13 15:49:412014/01/13
To: Deryk Lyu、Constantine Plotnikov、scala-user
The main use-case is composition.

If you want to use `Future.traverse` or `Future.sequence`, then the overall result will be a failure if any one element fails.

A `Future[Try[T]]` can "succeed" with a `Failure[T]`, allowing you to manage individual errors after a `sequence` or `traverse` operation has completed.
--
Kevin Wright
mail: kevin....@scalatechnology.com
gtalk / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright
steam: kev_lee_wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

Deryk Lyu

未読、
2014/01/13 23:14:332014/01/13
To: √iktor Ҡlang、Constantine Plotnikov、scala-user
Exactly, since Try is already embedded in future. I am really confusing in what cases we need Future[Try[T]].

Deryk Lyu

未読、
2014/01/13 23:23:592014/01/13
To: Kevin Wright、Constantine Plotnikov、scala-user
OK. Since "A `Future[Try[T]]` can "succeed" with a `Failure[T]", then there would be no failures for Future[Try[T]], is it true?

 Let me try one example:

val getfriend: Future[Try[String]] = future {
    try(session.getfriends());
}

getfriend onCompletion {
    case Success(flist) =>  println("Get friends list successfully");
    case Failure(t) => println("fail to retrieve friends list");
}

In the above example, the result will always be "Get friends list successfully" even if "flist" itself is a "failure".
Then when can "getfriend" get failed?

Thanks
Deryk

√iktor Ҡlang

未読、
2014/01/14 5:23:012014/01/14
To: Deryk Lyu、Kevin Wright、Constantine Plotnikov、scala-user
On Tue, Jan 14, 2014 at 5:23 AM, Deryk Lyu <dery...@gmail.com> wrote:
OK. Since "A `Future[Try[T]]` can "succeed" with a `Failure[T]", then there would be no failures for Future[Try[T]], is it true?

 Let me try one example:

val getfriend: Future[Try[String]] = future {
    try(session.getfriends());
}

getfriend onCompletion {
    case Success(flist) =>  println("Get friends list successfully");
    case Failure(t) => println("fail to retrieve friends list");
}

In the above example, the result will always be "Get friends list successfully" even if "flist" itself is a "failure".
Then when can "getfriend" get failed?

Correction:

 getfriend onCompletion {
    case Success(Success(flist)) =>  println("Get friends list successfully")
    case Success(Failure(t)) => println("fail to retrieve friends list")
    case Failure(t) => println("disturbance in the force")
}


The problem with Future[Try[T]] is that it doesn't preclude the Future itself failing.
What if the ExecutionContext is shutdown and completes the Future with an ExecutionException?

Let's take an example:

λ  ~  scala
impWelcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.concurrent._
import scala.concurrent._

scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global

scala> import scala.util.Try
import scala.util.Try

scala> def bippy(f: Future[Try[Unit]]): Unit = f onComplete println
bippy: (f: scala.concurrent.Future[scala.util.Try[Unit]])Unit

scala> bippy(Future failed new Exception)
scala> Failure(java.lang.Exception)

scala> bippy(Future successful Try(()))
Success(Success(()))

scala> bippy(Future successful Try(throw null))
Success(Failure(java.lang.NullPointerException))

Conclusion: The lifting doesn't really buy anything (at least to me)

Cheers,



--
Cheers,

Viktor Klang

Director of Engineering

Twitter: @viktorklang

Naftoli Gugenheim

未読、
2014/01/21 18:07:432014/01/21
To: Deryk Lyu、scala-user、Constantine Plotnikov、Kevin Wright

It will only "succeed" with a Failure if you manually return a Failure. If an exception is not caught, the Future itself will fail.

Filippo De Luca

未読、
2014/01/21 18:40:492014/01/21
To: √iktor Ҡlang、scala...@googlegroups.com、Deryk Lyu、Constantine Plotnikov、Kevin Wright

Is it a good idea to flatten Future[Try[T]]?

全員に返信
投稿者に返信
転送
新着メール 0 件