package jsbrucker
Package Members
- package result
Error handling with the Result type.
Use Case
Error handling with the Result type.
Resultis 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
Resultwhenever errors are expected and recoverable.For simplicity many examples make use of primitives such as
StringandIntfor 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
Resultmight 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, butResultcomes 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,
Resultprovides a wide variety of different methods.Querying the variant
The isOk and isErr methods return
trueif theResultisOkorErr, respectively.The isOkAnd and isErrAnd methods take in a predicate and return
trueif theResultisOkorErrrespectively, and the predicate returnstruewhen applied to the contained value.The contains and containsErr methods take in a value and return
trueif it matches the innerOkorErrvalue respectively.Transforming contained values
These methods transform
ResulttoOption:- err transforms
Result[E, T]intoOption[E], mappingErr(e)toSome(e)andOk(v)toNone - ok transforms
Result[E, T]intoOption[T], mappingOk(v)toSome(v)andErr(e)toNone - transposeOption transposes a
Result[E, Option[T]]into anOption[Result[E, T]] - transposeOptionErr transposes a
Result[Option[E], T]into anOption[Result[E, T]]
This method transforms the contained value of the
Okvariant:- map transforms
Result[E, T]intoResult[E, U]by applying the provided function to the contained value ofOkand leavingErrvalues unchanged
This method transforms the contained value of the
Errvariant:- mapErr transforms
Result[E, T]intoResult[F, T]by applying the provided function to the contained value ofErrand leavingOkvalues unchanged
These methods transform a
Result[E, T]into a value of a possibly different typeU:- mapOr and mapErrOr applies the
provided function to the contained value of
OkorErrrespecitively, or returns the provided default value. - mapOrElse and mapErrOrElse
applies the provided function to the contained value of
OkorErrrespectively, or applies the provided default fallback function to the contained value ofErrorOkrespectively.
These methods transform
ResulttoFuture:- transposeFuture transposes a
Result[E, Future[T]]into aFuture[Result[E, T]] - transposeFutureErr transposes a
Result[Future[E], T]into aFuture[Result[E, T]]
Extracting contained values
These methods extract the contained value in a
Result[E, T]when it is theOkvariant. If theResultisErr:- 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 theErrvariant. If theResultisOk:Boolean operators
These methods treat the
Resultas a boolean value, whereOkacts liketrueandErracts likefalse. There are two categories of these methods: ones that take aResultas input, and ones that take a function as input (to be lazily evaluated).The and and or methods take another
Resultas input, and produce aResultas output. Theandmethod can produce aResult[E, U]value having a different inner typeUthanResult[E, T]. Theormethod can produce aResult[F, T]value having a different error typeFthanResult[E, T].method
self
input
output
andErr(e)(ignored)
Err(e)andOk(x)Err(d)Err(d)andOk(x)Ok(y)Ok(y)orErr(e)Err(d)Err(d)orErr(e)Ok(y)Ok(y)orOk(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
andThenmethod can produce aResult[E, U]value having a different inner typeUthanResult[E, T]. TheorElsemethod can produce aResult[F, T]value having a different error typeFthanResult[E, T].NOTE: flatMap is equivalent to
andThenand it is provided for consistency with typical Scala conventions. Along those lines flatMapErr is equivalent toorElse.method
self
function input
function result
output
andThenErr(e)(not provided)
(not evaluated)
Err(e)andThenOk(x)xErr(d)Err(d)andThenOk(x)xOk(y)Ok(y)orElseErr(e)eErr(d)Err(d)orElseErr(e)eOk(y)Ok(y)orElseOk(x)(not provided)
(not evaluated)
Ok(x)Implicits
Extension methods are provided to facilitate conversion of several types to a
Result. They can imported usingimport dev.jsbrucker.result.implicits._- All types get some extension methods out of the box. This includes:
Optiongets a number of additional helpers. See: extensions.option.Ops- When using Scala 2.13 extensions.iterable_ops.Ops is available for
processing collections of
Results.
- Note
This documentation began as a derivative of the Rust Result<T, E> documentation
- err transforms