According to the documentation:
The Try type represents a computation that may either result in an exception, or return a successfully computed value. It's similar to, but semantically different from the scala.util.Either type.
The docs do not go into further detail as to what the semantic difference is. Both seem to be able to communicate successes and failures. Why would you use one over the other?
Show activity on this post. With unit = Try , Try is not a monad, because the left unit law fails.
The Try type represents a computation that may either result in an exception, or return a successfully computed value. It's similar to, but semantically different from the scala. util. Either type. Instances of Try[T] , are either an instance of scala.
In Scala Either, functions exactly similar to an Option. The only dissimilarity is that with Either it is practicable to return a string which can explicate the instructions about the error that appeared.
I covered the relationship between Try
, Either
, and Option
in this answer. The highlights from there regarding the relationship between Try
and Either
are summarized below:
Try[A]
is isomorphic to Either[Throwable, A]
. In other words you can treat a Try
as an Either
with a left type of Throwable
, and you can treat any Either
that has a left type of Throwable
as a Try
. It is conventional to use Left
for failures and Right
for successes.
Of course, you can also use Either
more broadly, not only in situations with missing or exceptional values. There are other situations where Either
can help express the semantics of a simple union type (where value is one of two types).
Semantically, you might use Try
to indicate that the operation might fail. You might similarly use Either
in such a situation, especially if your "error" type is something other than Throwable
(e.g. Either[ErrorType, SuccessType]
). And then you might also use Either
when you are operating over a union type (e.g. Either[PossibleType1, PossibleType2]
).
The standard library does not include the conversions from Either
to Try
or from Try
to Either
, but it is pretty simple to enrich Try
, and Either
as needed:
object TryEitherConversions { implicit class EitherToTry[L <: Throwable, R](val e: Either[L, R]) extends AnyVal { def toTry: Try[R] = e.fold(Failure(_), Success(_)) } implicit class TryToEither[T](val t: Try[T]) extends AnyVal { def toEither: Either[Throwable, T] = t.map(Right(_)).recover(PartialFunction(Left(_))).get } }
This would allow you to do:
import TryEitherConversions._ //Try to Either Try(1).toEither //Either[Throwable, Int] = Right(1) Try("foo".toInt).toEither //Either[Throwable, Int] = Left(java.lang.NumberFormatException) //Either to Try Right[Throwable, Int](1).toTry //Success(1) Left[Throwable, Int](new Exception).toTry //Failure(java.lang.Exception)
To narrowly answer your question: "What's the semantic difference":
This probably refers to flatMap and map, which are non-existent in Either and either propagate failure or map the success value in Try. This allows, for instance, chaining like
for { a <- Try {something} b <- Try {somethingElse(a)} c <- Try {theOtherThing(b)} } yield c
which does just what you'd hope - returns a Try containing either the first exception, or the result.
Try has lots of other useful methods, and of course its companion apply method, that make it very convenient for its intended use - exception handling.
If you really want to be overwhelmed, there are two other classes out there which may be of interest for this kind of application. Scalaz has a class called "\/" (formerly known as Prince), pronounced "Either", which is mostly like Either, but flatMap and map work on the Right value. Similarly, and not, Scalactic has an "Or" which is also similar to Either, but flatMap and map work on the Left value.
I don't recommend Scalaz for beginners.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With