summaryrefslogtreecommitdiff
path: root/src/library/scala/util/Try.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/scala/util/Try.scala')
-rw-r--r--src/library/scala/util/Try.scala148
1 files changed, 84 insertions, 64 deletions
diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala
index b0eae74043..00e9585c38 100644
--- a/src/library/scala/util/Try.scala
+++ b/src/library/scala/util/Try.scala
@@ -9,9 +9,7 @@
package scala
package util
-import scala.collection.Seq
import scala.util.control.NonFatal
-import scala.language.implicitConversions
/**
* The `Try` type represents a computation that may either result in an exception, or return a
@@ -61,7 +59,7 @@ import scala.language.implicitConversions
* @author based on Twitter's original implementation in com.twitter.util.
* @since 2.10
*/
-sealed abstract class Try[+T] {
+sealed abstract class Try[+T] extends Product with Serializable {
/** Returns `true` if the `Try` is a `Failure`, `false` otherwise.
*/
@@ -75,16 +73,11 @@ sealed abstract class Try[+T] {
*
* ''Note:'': This will throw an exception if it is not a success and default throws an exception.
*/
- def getOrElse[U >: T](default: => U): U =
- if (isSuccess) get else default
+ def getOrElse[U >: T](default: => U): U
/** Returns this `Try` if it's a `Success` or the given `default` argument if this is a `Failure`.
*/
- def orElse[U >: T](default: => Try[U]): Try[U] =
- try if (isSuccess) this else default
- catch {
- case NonFatal(e) => Failure(e)
- }
+ def orElse[U >: T](default: => Try[U]): Try[U]
/** Returns the value from this `Success` or throws the exception if this is a `Failure`.
*/
@@ -108,6 +101,11 @@ sealed abstract class Try[+T] {
def map[U](f: T => U): Try[U]
/**
+ * Applies the given partial function to the value from this `Success` or returns this if this is a `Failure`.
+ */
+ def collect[U](pf: PartialFunction[T, U]): Try[U]
+
+ /**
* Converts this to a `Failure` if the predicate is not satisfied.
*/
def filter(p: T => Boolean): Try[T]
@@ -134,6 +132,7 @@ sealed abstract class Try[+T] {
* collection" contract even though it seems unlikely to matter much in a
* collection with max size 1.
*/
+ @deprecatedInheritance("You were never supposed to be able to extend this class.", "2.12.0")
class WithFilter(p: T => Boolean) {
def map[U](f: T => U): Try[U] = Try.this filter p map f
def flatMap[U](f: T => Try[U]): Try[U] = Try.this filter p flatMap f
@@ -145,18 +144,18 @@ sealed abstract class Try[+T] {
* Applies the given function `f` if this is a `Failure`, otherwise returns this if this is a `Success`.
* This is like `flatMap` for the exception.
*/
- def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U]
+ def recoverWith[U >: T](@deprecatedName('f) pf: PartialFunction[Throwable, Try[U]]): Try[U]
/**
* Applies the given function `f` if this is a `Failure`, otherwise returns this if this is a `Success`.
* This is like map for the exception.
*/
- def recover[U >: T](f: PartialFunction[Throwable, U]): Try[U]
+ def recover[U >: T](@deprecatedName('f) pf: PartialFunction[Throwable, U]): Try[U]
/**
* Returns `None` if this is a `Failure` or a `Some` containing the value if this is a `Success`.
*/
- def toOption: Option[T] = if (isSuccess) Some(get) else None
+ def toOption: Option[T]
/**
* Transforms a nested `Try`, ie, a `Try` of type `Try[Try[T]]`,
@@ -173,13 +172,31 @@ sealed abstract class Try[+T] {
/** Completes this `Try` by applying the function `f` to this if this is of type `Failure`, or conversely, by applying
* `s` if this is a `Success`.
*/
- def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U] =
- try this match {
- case Success(v) => s(v)
- case Failure(e) => f(e)
- } catch {
- case NonFatal(e) => Failure(e)
- }
+ def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U]
+
+ /**
+ * Returns `Left` with `Throwable` if this is a `Failure`, otherwise returns `Right` with `Success` value.
+ */
+ def toEither: Either[Throwable, T]
+
+ /**
+ * Applies `fa` if this is a `Failure` or `fb` if this is a `Success`.
+ * If `fb` is initially applied and throws an exception,
+ * then `fa` is applied with this exception.
+ *
+ * @example {{{
+ * val result: Try[Throwable, Int] = Try { string.toInt }
+ * log(result.fold(
+ * ex => "Operation failed with " + ex,
+ * v => "Operation produced value: " + v
+ * ))
+ * }}}
+ *
+ * @param fa the function to apply if this is a `Failure`
+ * @param fb the function to apply if this is a `Success`
+ * @return the results of applying the function
+ */
+ def fold[U](fa: Throwable => U, fb: T => U): U
}
@@ -192,57 +209,60 @@ object Try {
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
-
}
final case class Failure[+T](exception: Throwable) extends Try[T] {
- def isFailure: Boolean = true
- def isSuccess: Boolean = false
- def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] =
- try {
- if (f isDefinedAt exception) f(exception) else this
- } catch {
- case NonFatal(e) => Failure(e)
- }
- def get: T = throw exception
- def flatMap[U](f: T => Try[U]): Try[U] = this.asInstanceOf[Try[U]]
- def flatten[U](implicit ev: T <:< Try[U]): Try[U] = this.asInstanceOf[Try[U]]
- def foreach[U](f: T => U): Unit = ()
- def map[U](f: T => U): Try[U] = this.asInstanceOf[Try[U]]
- def filter(p: T => Boolean): Try[T] = this
- def recover[U >: T](rescueException: PartialFunction[Throwable, U]): Try[U] =
- try {
- if (rescueException isDefinedAt exception) {
- Try(rescueException(exception))
- } else this
- } catch {
- case NonFatal(e) => Failure(e)
- }
- def failed: Try[Throwable] = Success(exception)
+ override def isFailure: Boolean = true
+ override def isSuccess: Boolean = false
+ override def get: T = throw exception
+ override def getOrElse[U >: T](default: => U): U = default
+ override def orElse[U >: T](default: => Try[U]): Try[U] =
+ try default catch { case NonFatal(e) => Failure(e) }
+ override def flatMap[U](f: T => Try[U]): Try[U] = this.asInstanceOf[Try[U]]
+ override def flatten[U](implicit ev: T <:< Try[U]): Try[U] = this.asInstanceOf[Try[U]]
+ override def foreach[U](f: T => U): Unit = ()
+ override def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U] =
+ try f(exception) catch { case NonFatal(e) => Failure(e) }
+ override def map[U](f: T => U): Try[U] = this.asInstanceOf[Try[U]]
+ override def collect[U](pf: PartialFunction[T, U]): Try[U] = this.asInstanceOf[Try[U]]
+ override def filter(p: T => Boolean): Try[T] = this
+ override def recover[U >: T](@deprecatedName('rescueException) pf: PartialFunction[Throwable, U]): Try[U] =
+ try { if (pf isDefinedAt exception) Success(pf(exception)) else this } catch { case NonFatal(e) => Failure(e) }
+ override def recoverWith[U >: T](@deprecatedName('f) pf: PartialFunction[Throwable, Try[U]]): Try[U] =
+ try { if (pf isDefinedAt exception) pf(exception) else this } catch { case NonFatal(e) => Failure(e) }
+ override def failed: Try[Throwable] = Success(exception)
+ override def toOption: Option[T] = None
+ override def toEither: Either[Throwable, T] = Left(exception)
+ override def fold[U](fa: Throwable => U, fb: T => U): U = fa(exception)
}
final case class Success[+T](value: T) extends Try[T] {
- def isFailure: Boolean = false
- def isSuccess: Boolean = true
- def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] = this
- def get = value
- def flatMap[U](f: T => Try[U]): Try[U] =
- try f(value)
- catch {
- case NonFatal(e) => Failure(e)
- }
- def flatten[U](implicit ev: T <:< Try[U]): Try[U] = value
- def foreach[U](f: T => U): Unit = f(value)
- def map[U](f: T => U): Try[U] = Try[U](f(value))
- def filter(p: T => Boolean): Try[T] = {
+ override def isFailure: Boolean = false
+ override def isSuccess: Boolean = true
+ override def get = value
+ override def getOrElse[U >: T](default: => U): U = get
+ override def orElse[U >: T](default: => Try[U]): Try[U] = this
+ override def flatMap[U](f: T => Try[U]): Try[U] =
+ try f(value) catch { case NonFatal(e) => Failure(e) }
+ override def flatten[U](implicit ev: T <:< Try[U]): Try[U] = value
+ override def foreach[U](f: T => U): Unit = f(value)
+ override def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U] = this flatMap s
+ override def map[U](f: T => U): Try[U] = Try[U](f(value))
+ override def collect[U](pf: PartialFunction[T, U]): Try[U] =
try {
- if (p(value)) this
+ if (pf isDefinedAt value) Success(pf(value))
else Failure(new NoSuchElementException("Predicate does not hold for " + value))
- } catch {
- case NonFatal(e) => Failure(e)
- }
- }
- def recover[U >: T](rescueException: PartialFunction[Throwable, U]): Try[U] = this
- def failed: Try[Throwable] = Failure(new UnsupportedOperationException("Success.failed"))
+ } catch { case NonFatal(e) => Failure(e) }
+ override def filter(p: T => Boolean): Try[T] =
+ try {
+ if (p(value)) this else Failure(new NoSuchElementException("Predicate does not hold for " + value))
+ } catch { case NonFatal(e) => Failure(e) }
+ override def recover[U >: T](@deprecatedName('rescueException) pf: PartialFunction[Throwable, U]): Try[U] = this
+ override def recoverWith[U >: T](@deprecatedName('f) pf: PartialFunction[Throwable, Try[U]]): Try[U] = this
+ override def failed: Try[Throwable] = Failure(new UnsupportedOperationException("Success.failed"))
+ override def toOption: Option[T] = Some(value)
+ override def toEither: Either[Throwable, T] = Right(value)
+ override def fold[U](fa: Throwable => U, fb: T => U): U =
+ try { fb(value) } catch { case NonFatal(e) => fa(e) }
}