Packages

  • package root
    Definition Classes
    root
  • package dev
    Definition Classes
    root
  • package jsbrucker
    Definition Classes
    dev
  • package result

    Error handling with the Result type.

    Use Case

    Error handling with the Result type.

    Result is a type used for returning and propagating errors. It is an disjoint union with the variants, Ok, representing success and containing a value, and Err, representing error and containing an error value.

    Functions should return Result whenever errors are expected and recoverable.

    For simplicity many examples make use of primitives such as String and Int for the error type. It is recommended that in practice developers should try to make use of more structured types to allow for improved error handling. As opposed to relying on a stringly-typed interface or integer error codes.

    A simple function returning Result might be defined and used like so:

    >>> import dev.jsbrucker.result._
    >>> sealed trait MajorVersion
    >>> object MajorVersion {
    ...   case object V1 extends MajorVersion
    ...   case object V2 extends MajorVersion
    ... }
    
    >>> sealed trait ParseError
    >>> object ParseError {
    ...  case object InvalidHeaderLength extends ParseError
    ...  case object UnsupportedVersion extends ParseError
    ... }
    
    >>> def parseMajorVersion(header: List[Int]): Result[ParseError, MajorVersion] =
    ...   header.headOption match {
    ...     case None    => Err(ParseError.InvalidHeaderLength)
    ...     case Some(1) => Ok(MajorVersion.V1)
    ...     case Some(2) => Ok(MajorVersion.V2)
    ...     case _       => Err(ParseError.UnsupportedVersion)
    ...   }
    
    >>> val version = parseMajorVersion(List(1, 2, 3, 4))
    >>> version match {
    ...   case Ok(v)  => "working with version: " + v.toString
    ...   case Err(e) => "error parsing header: " + e.toString
    ... }
    working with version: V1

    Pattern matching on Results is clear and straightforward for simple cases, but Result comes with some convenience methods that make working with it more succinct.

    >>> import dev.jsbrucker.result._
    >>> val goodResult: Result[String, Int] = Ok(10);
    >>> val badResult: Result[String, Int] = Err("Some Error")
    
    // The `isOk` and `isErr` methods do what they say.
    
    >>> goodResult.isOk && !goodResult.isErr
    true
    
    >>> badResult.isErr && !badResult.isOk
    true
    
    // `map` replaces the `Ok` value of a `Result` with the result of the provided function
    >>> goodResult.map(_ + 1)
    Ok(11)
    
    // `map` leaves an `Err` value of a `Result` as it was, ignoring the provided function
    >>> badResult.map(_ - 1)
    Err(Some Error)
    
    // Use `andThen` to continue the computation.
    scala> goodResult.andThen(i => Ok(i == 11))
    res0: Result[String, Boolean] = Ok(false)
    
    // Use `orElse` to handle the error.
    scala> badResult.orElse {
         |   case "Anticipated Error" => Ok(0)
         |   case "Some Error"        => Err(true)
         |   case _                   => Err(false)
         | }
    res1: Result[Boolean, Int] = Err(true)

    Method overview

    In addition to working with pattern matching, Result provides a wide variety of different methods.

    Querying the variant

    The isOk and isErr methods return true if the Result is Ok or Err, respectively.

    The isOkAnd and isErrAnd methods take in a predicate and return true if the Result is Ok or Err respectively, and the predicate returns true when applied to the contained value.

    The contains and containsErr methods take in a value and return true if it matches the inner Ok or Err value respectively.

    Transforming contained values

    These methods transform Result to Option:

    • err transforms Result[E, T] into Option[E], mapping Err(e) to Some(e) and Ok(v) to None
    • ok transforms Result[E, T] into Option[T], mapping Ok(v) to Some(v) and Err(e) to None
    • transposeOption transposes a Result[E, Option[T]] into an Option[Result[E, T]]
    • transposeOptionErr transposes a Result[Option[E], T] into an Option[Result[E, T]]

    This method transforms the contained value of the Ok variant:

    • map transforms Result[E, T] into Result[E, U] by applying the provided function to the contained value of Ok and leaving Err values unchanged

    This method transforms the contained value of the Err variant:

    • mapErr transforms Result[E, T] into Result[F, T] by applying the provided function to the contained value of Err and leaving Ok values unchanged

    These methods transform a Result[E, T] into a value of a possibly different type U:

    • mapOr and mapErrOr applies the provided function to the contained value of Ok or Err respecitively, or returns the provided default value.
    • mapOrElse and mapErrOrElse applies the provided function to the contained value of Ok or Err respectively, or applies the provided default fallback function to the contained value of Err or Ok respectively.

    These methods transform Result to Future:

    Extracting contained values

    These methods extract the contained value in a Result[E, T] when it is the Ok variant. If the Result is Err:

    • expect panics with a provided custom message
    • unwrap panics with a generic message
    • unwrapOr returns the provided default value
    • unwrapOrElse returns the result of evaluating the provided function

    These methods extract the contained value in a Result[E, T] when it is the Err variant. If the Result is Ok:

    Boolean operators

    These methods treat the Result as a boolean value, where Ok acts like true and Err acts like false. There are two categories of these methods: ones that take a Result as input, and ones that take a function as input (to be lazily evaluated).

    The and and or methods take another Result as input, and produce a Result as output. The and method can produce a Result[E, U] value having a different inner type U than Result[E, T]. The or method can produce a Result[F, T] value having a different error type F than Result[E, T].

    method

    self

    input

    output

    and

    Err(e)

    (ignored)

    Err(e)

    and

    Ok(x)

    Err(d)

    Err(d)

    and

    Ok(x)

    Ok(y)

    Ok(y)

    or

    Err(e)

    Err(d)

    Err(d)

    or

    Err(e)

    Ok(y)

    Ok(y)

    or

    Ok(x)

    (ignored)

    Ok(x)

    The andThen and orElse methods take a function as input, and only evaluate the function when they need to produce a new value. The andThen method can produce a Result[E, U] value having a different inner type U than Result[E, T]. The orElse method can produce a Result[F, T] value having a different error type F than Result[E, T].

    NOTE: flatMap is equivalent to andThen and it is provided for consistency with typical Scala conventions. Along those lines flatMapErr is equivalent to orElse.

    method

    self

    function input

    function result

    output

    andThen

    Err(e)

    (not provided)

    (not evaluated)

    Err(e)

    andThen

    Ok(x)

    x

    Err(d)

    Err(d)

    andThen

    Ok(x)

    x

    Ok(y)

    Ok(y)

    orElse

    Err(e)

    e

    Err(d)

    Err(d)

    orElse

    Err(e)

    e

    Ok(y)

    Ok(y)

    orElse

    Ok(x)

    (not provided)

    (not evaluated)

    Ok(x)

    Implicits

    Extension methods are provided to facilitate conversion of several types to a Result. They can imported using import dev.jsbrucker.result.implicits._

    Definition Classes
    jsbrucker
    Note

    This documentation began as a derivative of the Rust Result<T, E> documentation

  • package extensions
    Definition Classes
    result
  • Err
  • FromResult
  • Ok
  • Result
  • ToResult
  • implicits

object Result

Linear Supertypes
AnyRef, Any
Ordering
  1. Grouped
  2. Alphabetic
  3. By Inheritance
Inherited
  1. Result
  2. AnyRef
  3. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. Protected

Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##: Int
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  4. def apply[E, T, V](value: V)(implicit toResult: ToResult[E, T, V]): Result[E, T]

    Allows for construction of a Result[E, T] from an arbitrary type V

    Allows for construction of a Result[E, T] from an arbitrary type V

    NOTE: ToResult has a implicits defined for Either and Try

    Examples
    >>> sealed trait Case
    >>> case class Bad(str: String) extends Case
    >>> case class Good(value: Int) extends Case
    
    >>> val goodInt = 1
    >>> val good = Good(goodInt)
    >>> val badStr = "Error"
    >>> val bad = Bad(badStr)
    
    >>> implicit val resultFromCase: ToResult[String, Int, Case] = {
    ...   case Good(v) => Ok(v)
    ...   case Bad(e) => Err(e)
    ... }
    
    >>> Result(good) == Ok(goodInt)
    true
    
    >>> Result(bad) == Err(badStr)
    true
  5. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  6. def clone(): AnyRef
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.CloneNotSupportedException]) @native() @IntrinsicCandidate()
  7. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  8. def equals(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef → Any
  9. final def getClass(): Class[_ <: AnyRef]
    Definition Classes
    AnyRef → Any
    Annotations
    @native() @IntrinsicCandidate()
  10. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native() @IntrinsicCandidate()
  11. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  12. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  13. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native() @IntrinsicCandidate()
  14. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native() @IntrinsicCandidate()
  15. final def synchronized[T0](arg0: => T0): T0
    Definition Classes
    AnyRef
  16. def toString(): String
    Definition Classes
    AnyRef → Any
  17. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])
  18. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException]) @native()
  19. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])

Deprecated Value Members

  1. def finalize(): Unit
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.Throwable]) @Deprecated
    Deprecated

Inherited from AnyRef

Inherited from Any

Extract

Ungrouped