Scala Library: scala.util.Try
scala.util.Try
sealed abstract class Try[+T] extends Product with Serializable
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.util.Success [T] or
scala.util.Failure [T].
For example, Try
can be used to perform division on a user-defined input,
without the need to do explicit exception-handling in all of the places that an
exception might occur.
Example:
import scala.io.StdIn
import scala.util.{Try, Success, Failure}
def divide: Try[Int] = {
val dividend = Try(StdIn.readLine("Enter an Int that you'd like to divide:\n").toInt)
val divisor = Try(StdIn.readLine("Enter an Int that you'd like to divide by:\n").toInt)
val problem = dividend.flatMap(x => divisor.map(y => x/y))
problem match {
case Success(v) =>
println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v)
Success(v)
case Failure(e) =>
println("You must've divided by zero or entered something that's not an Int. Try again!")
println("Info from the exception: " + e.getMessage)
divide
}
}
An important property of Try
shown in the above example is its ability to _
pipeline_ , or chain, operations, catching exceptions along the way. The
flatMap
and map
combinators in the above example each essentially pass off
either their successfully completed value, wrapped in the Success
type for it
to be further operated upon by the next combinator in the chain, or the
exception wrapped in the Failure
type usually to be simply passed on down the
chain. Combinators such as recover
and recoverWith
are designed to provide
some type of default behavior in the case of failure.
Note : only non-fatal exceptions are caught by the combinators on Try
(see
scala.util.control.NonFatal). Serious system errors, on the other hand, will be
thrown.
Note: : all Try combinators will catch exceptions and return failure unless otherwise specified in the documentation.
Try
comes to the Scala standard library after years of use as an integral
part of Twitter’s stack.
- Source
- Since
- 2.10
Type Members
class WithFilter extends AnyRef
We need a whole WithFilter class to honor the “doesn’t create a new collection” contract even though it seems unlikely to matter much in a collection with max size 1.
- Annotations
- @ deprecatedInheritance (message =…, since = “2.12”)
- Source
Abstract Value Members From scala.Equals
abstract def canEqual(that: Any): Boolean
A method that should be called from every well-designed equals method that is open to be overridden in a subclass. See Programming in Scala, Chapter 28 for discussion and design.
- that
- the value being probed for possible equality
- returns
- true if this instance can possibly equal
that
, otherwise false
- true if this instance can possibly equal
- Definition Classes
- Equals
(defined at scala.Equals)
Abstract Value Members From scala.Product
abstract def productElement(n: Int): Any
The n th element of this product, 0-based. In other words, for a
product A(x1, ..., xk)
, returns x(n+1)
where 0 < n < k
.
- n
- the index of the element to return
- returns
- the element
n
elements after the first element
- the element
- Definition Classes
- Product
- Exceptions thrown *
(defined at scala.Product)
Abstract Value Members From scala.util.Try
abstract def collect[U](pf: PartialFunction[T, U]): Try[U]
Applies the given partial function to the value from this Success
or returns
this if this is a Failure
.
(defined at scala.util.Try)
abstract def failed: Try[Throwable]
Inverts this Try
. If this is a Failure
, returns its exception wrapped in a
Success
. If this is a Success
, returns a Failure
containing an
UnsupportedOperationException
.
(defined at scala.util.Try)
abstract def filter(p: (T) ⇒ Boolean): Try[T]
Converts this to a Failure
if the predicate is not satisfied.
(defined at scala.util.Try)
abstract def flatMap[U](f: (T) ⇒ Try[U]): Try[U]
Returns the given function applied to the value from this Success
or returns
this if this is a Failure
.
(defined at scala.util.Try)
abstract def flatten[U](implicit ev: <:<[T, Try[U]]): Try[U]
Transforms a nested Try
, ie, a Try
of type Try[Try[T]]
, into an
un-nested Try
, ie, a Try
of type Try[T]
.
(defined at scala.util.Try)
abstract def fold[U](fa: (Throwable) ⇒ U, fb: (T) ⇒ U): U
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.
- fa
- the function to apply if this is a
Failure
- the function to apply if this is a
- fb
- the function to apply if this is a
Success
- the function to apply if this is a
- returns
- the results of applying the function
Example:
val result: Try[Throwable, Int] = Try { string.toInt }
log(result.fold(
ex => "Operation failed with " + ex,
v => "Operation produced value: " + v
))
(defined at scala.util.Try)
abstract def foreach[U](f: (T) ⇒ U): Unit
Applies the given function f
if this is a Success
, otherwise returns
Unit
if this is a Failure
.
Note: If f
throws, then this method may throw an exception.
(defined at scala.util.Try)
abstract def getOrElse[U >: T](default: ⇒ U): U
Returns the value from this Success
or the given default
argument if this is
a Failure
.
Note: : This will throw an exception if it is not a success and default throws an exception.
(defined at scala.util.Try)
abstract def map[U](f: (T) ⇒ U): Try[U]
Maps the given function to the value from this Success
or returns this if this
is a Failure
.
(defined at scala.util.Try)
abstract def orElse[U >: T](default: ⇒ Try[U]): Try[U]
Returns this Try
if it’s a Success
or the given default
argument if this
is a Failure
.
(defined at scala.util.Try)
abstract def recoverWith[U >: T](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 flatMap
for the exception.
(defined at scala.util.Try)
abstract def recover[U >: T](pf: PartialFunction[Throwable, 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.
(defined at scala.util.Try)
abstract def toEither: Either[Throwable, T]
Returns Left
with Throwable
if this is a Failure
, otherwise returns
Right
with Success
value.
(defined at scala.util.Try)
abstract def transform[U](s: (T) ⇒ Try[U], f: (Throwable) ⇒ Try[U]): Try[U]
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
.
(defined at scala.util.Try)
Concrete Value Members From scala.util.Try
abstract def get: T
Returns the value from this Success
or throws the exception if this is a
Failure
.
(defined at scala.util.Try)
final def withFilter(p: (T) ⇒ Boolean): WithFilter
Creates a non-strict filter, which eventually converts this to a Failure
if
the predicate is not satisfied.
Note: unlike filter, withFilter does not create a new Try. Instead, it restricts
the domain of subsequent map
, flatMap
, foreach
, and withFilter
operations.
As Try is a one-element collection, this may be a bit overkill, but it’s consistent with withFilter on Option and the other collections.
- p
- the predicate used to test elements.
- returns
- an object of class
WithFilter
, which supportsmap
,flatMap
,foreach
, andwithFilter
operations. All these operations apply to those elements of this Try which satisfy the predicatep
.
- an object of class
- Annotations
- @ inline () (defined at scala.util.Try)
Full Source:
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2008-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala
package util
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
* 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.util.Success]][T] or [[scala.util.Failure]][T].
*
* For example, `Try` can be used to perform division on a user-defined input, without the need to do explicit
* exception-handling in all of the places that an exception might occur.
*
* Example:
* {{{
* import scala.io.StdIn
* import scala.util.{Try, Success, Failure}
*
* def divide: Try[Int] = {
* val dividend = Try(StdIn.readLine("Enter an Int that you'd like to divide:\n").toInt)
* val divisor = Try(StdIn.readLine("Enter an Int that you'd like to divide by:\n").toInt)
* val problem = dividend.flatMap(x => divisor.map(y => x/y))
* problem match {
* case Success(v) =>
* println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v)
* Success(v)
* case Failure(e) =>
* println("You must've divided by zero or entered something that's not an Int. Try again!")
* println("Info from the exception: " + e.getMessage)
* divide
* }
* }
*
* }}}
*
* An important property of `Try` shown in the above example is its ability to ''pipeline'', or chain, operations,
* catching exceptions along the way. The `flatMap` and `map` combinators in the above example each essentially
* pass off either their successfully completed value, wrapped in the `Success` type for it to be further operated
* upon by the next combinator in the chain, or the exception wrapped in the `Failure` type usually to be simply
* passed on down the chain. Combinators such as `recover` and `recoverWith` are designed to provide some type of
* default behavior in the case of failure.
*
* ''Note'': only non-fatal exceptions are caught by the combinators on `Try` (see [[scala.util.control.NonFatal]]).
* Serious system errors, on the other hand, will be thrown.
*
* ''Note:'': all Try combinators will catch exceptions and return failure unless otherwise specified in the documentation.
*
* `Try` comes to the Scala standard library after years of use as an integral part of Twitter's stack.
*
* @author based on Twitter's original implementation in com.twitter.util.
* @since 2.10
*/
sealed abstract class Try[+T] extends Product with Serializable {
/** Returns `true` if the `Try` is a `Failure`, `false` otherwise.
*/
def isFailure: Boolean
/** Returns `true` if the `Try` is a `Success`, `false` otherwise.
*/
def isSuccess: Boolean
/** Returns the value from this `Success` or the given `default` argument if this is a `Failure`.
*
* ''Note:'': This will throw an exception if it is not a success and default throws an exception.
*/
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]
/** Returns the value from this `Success` or throws the exception if this is a `Failure`.
*/
def get: T
/**
* Applies the given function `f` if this is a `Success`, otherwise returns `Unit` if this is a `Failure`.
*
* ''Note:'' If `f` throws, then this method may throw an exception.
*/
def foreach[U](f: T => U): Unit
/**
* Returns the given function applied to the value from this `Success` or returns this if this is a `Failure`.
*/
def flatMap[U](f: T => Try[U]): Try[U]
/**
* Maps the given function to the value from this `Success` or returns this if this is a `Failure`.
*/
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]
/** Creates a non-strict filter, which eventually converts this to a `Failure`
* if the predicate is not satisfied.
*
* Note: unlike filter, withFilter does not create a new Try.
* Instead, it restricts the domain of subsequent
* `map`, `flatMap`, `foreach`, and `withFilter` operations.
*
* As Try is a one-element collection, this may be a bit overkill,
* but it's consistent with withFilter on Option and the other collections.
*
* @param p the predicate used to test elements.
* @return an object of class `WithFilter`, which supports
* `map`, `flatMap`, `foreach`, and `withFilter` operations.
* All these operations apply to those elements of this Try
* which satisfy the predicate `p`.
*/
@inline final def withFilter(p: T => Boolean): WithFilter = new WithFilter(p)
/** We need a whole WithFilter class to honor the "doesn't create a new
* 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")
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
def foreach[U](f: T => U): Unit = Try.this filter p foreach f
def withFilter(q: T => Boolean): WithFilter = new WithFilter(x => p(x) && q(x))
}
/**
* 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](@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](@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]
/**
* Transforms a nested `Try`, ie, a `Try` of type `Try[Try[T]]`,
* into an un-nested `Try`, ie, a `Try` of type `Try[T]`.
*/
def flatten[U](implicit ev: T <:< Try[U]): Try[U]
/**
* Inverts this `Try`. If this is a `Failure`, returns its exception wrapped in a `Success`.
* If this is a `Success`, returns a `Failure` containing an `UnsupportedOperationException`.
*/
def failed: Try[Throwable]
/** 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]
/**
* 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
}
object Try {
/** Constructs a `Try` using the by-name parameter. This
* method will ensure any non-fatal exception is caught and a
* `Failure` object is returned.
*/
def apply[T](r: => T): Try[T] =
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
}
final case class Failure[+T](exception: Throwable) extends Try[T] {
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] {
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 (pf isDefinedAt value) Success(pf(value))
else Failure(new NoSuchElementException("Predicate does not hold for " + value))
} 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) }
}
Interested in Scala?
I send out weekly, personalized emails with articles and conference talks.
Subscribe now.