Resurge provides a simple, Rust-inspired Result type for Scala, designed to handle success and failure outcomes in computations, avoiding exceptions.
It models computations that can either succeed with a value (Ok) or fail with an error (Err).
This library is not yet published to public repositories like Maven Central, as it currently lacks extensive real-world usage and testing to ensure production readiness. However, it can be built and published locally for personal or internal use.
- Features
- Installation
- Usage
- Development
- License
Ok[T]: Represents successful results, holding a value of typeT.Err[E]: Represents failure, holding an error of typeE.- Error handling: Easily manage fallible operations without exceptions.
- Flexible APIs: Includes methods like
map,flatMap,fold,unwrapOrElse, and more. - Inspired by Rust: Provides a familiar structure for developers coming from Rust.
You can use this library in your Scala project by publishing it locally using sbt.
git clone https://github.com/Suopunki/Resurge
cd resurgesbt publishLocallibraryDependencies += "resurge" %% "resurge" % "0.1.0"This guide covers all methods available in the current API version (0.1.0).
isOkisErrisOkAndisErrAnd
expectexpectErrunwrapunwrapErrunwrapOrunwrapOrDefaultunwrapOrElse
mapmapErrmapOrmapOrElseflattenflatMapwithFilter
toOptiontoEither
fromTry
To use default values for your types when calling methods like unwrapOrDefault,
you need to declare implicit Default[T] instances for those types.
Here's an example for a simple case class:
case class Person(name: String, age: Int)
given Default[Person] with
def default: Person = Person("", 0)
val unwrappingDefault = Err("Failure").unwrapOrDefault // Person("", 0)Here are examples of how to use the different Result methods.
import resurge.*
def handleAndPrintResult[T, E](result: Result[T, E]): Unit = result match
case Ok(value) => println(s"Success with value: $value")
case Err(error) => println(s"Failure with error: $error")import resurge.*
@main def example(): Unit =
val successResult = Ok(42)
val failureResult = Err("Something went wrong")
// isOk(): Boolean
val isSuccessOk = successResult.isOk() // true
val isFailureOk = failureResult.isOk() // false
// isErr(): Boolean
val isSuccessErr = successResult.isErr() // false
val isFailureErr = failureResult.isErr() // true
// isOkAnd(f: T => Boolean): Boolean
val isSuccessOkAndTrue = successResult.isOkAnd(_ => true) // true
val isSuccessOkAndFalse = successResult.isOkAnd(_ => false) // false
val isFailureOkAndTrue = failureResult.isOkAnd(_ => true) // false
val isFailureOkAndFalse = failureResult.isOkAnd(_ => false) // false
// isErrAnd(f: E => Boolean): Boolean
val isSuccessErrAndTrue = successResult.isErrAnd(_ => true) // false
val isSuccessErrAndFalse = successResult.isErrAnd(_ => false) // false
val isFailureErrAndTrue = failureResult.isErrAnd(_ => true) // true
val isFailureErrAndFalse = failureResult.isErrAnd(_ => false) // falseimport resurge.*
@main def example(): Unit =
val successResult = Ok(42)
val failureResult = Err("Something went wrong")
// expect(message: String): T
val value1 = successResult.expect("Expected a value") // returns 42
// val value2 = failureResult.expect("Expected a value") // throws an exception with the message
// expectErr(message: String): E
val error1 = failureResult.expectErr("Expected an error") // returns "Something went wrong"
// val error2 = successResult.expectErr("Expected an error") // throws an exception
// unwrap: T
val unwrappedSuccess = successResult.unwrap // returns 42
// val unwrappedFailure = failureResult.unwrap // throws an exception
// unwrapErr: E
val unwrappedError = failureResult.unwrapErr // returns "Something went wrong"
// val unwrappedSuccessErr = successResult.unwrapErr // throws an exception
// unwrapOr[U >: T](default: => U): U
val valueOrDefault = successResult.unwrapOr(100) // 42
val failureOrDefault = failureResult.unwrapOr(100) // 100
// unwrapOrDefault[U >: T](using d: Default[U]): U
// Assuming you have Default[T] instances defined
given Default[Int] with
def default: Int = 99
val valueOrProvidedDefault = successResult.unwrapOrDefault // 42
val failureOrProvidedDefault = failureResult.unwrapOrDefault // 99
// unwrapOrElse[U >: T](f: E => U): U
// The fallback function is only evaluated if the result is Err
val valueOrElse = successResult.unwrapOrElse(err => err.length) // 42
val failureOrElse = failureResult.unwrapOrElse(err => err.length) // 20 ("Something went wrong".length)import resurge.*
@main def example(): Unit =
val successResult = Ok(42)
val failureResult = Err("Something went wrong")
// map[U](f: T => U): Result[U, E]
val mappedSuccess = successResult.map(_ * 2) // Ok(84)
val mappedFailure = failureResult.map(_ => 100) // Err("Something went wrong")
// mapErr[F](f: E => F): Result[T, F]
val mappedErrorSuccess = successResult.mapErr(_.toUpperCase) // Ok(42)
val mappedErrorFailure = failureResult.mapErr(_.toUpperCase) // Err("SOMETHING WENT WRONG")
// mapOr[U](f: T => U, default: U): U
val mapOrSuccess = successResult.mapOr(_ * 2, 0) // 84
val mapOrFailure = failureResult.mapOr(_ => 0, -1) // -1
// mapOrElse[U](f: T => U, fallback: E => U): U
val mapOrElseSuccess = successResult.mapOrElse(_ * 2, _.length) // 84
val mapOrElseFailure = failureResult.mapOrElse(_ => 0, _.length) // 20
// flatten[U, F >: E](using ev: T <:< Result[U, F]): Result[U, F]
val nestedOk: Result[Result[Int, String], String] = Ok(Ok(100))
val flattenedOk = nestedOk.flatten // Ok(100)
// flatMap[U, F >: E](f: T => Result[U, F]): Result[U, F]
val flatMappedSuccess = successResult.flatMap(v => Ok(v * 2)) // Ok(84)
val flatMappedFailure = failureResult.flatMap(v => Ok(v.length)) // Err("Something went wrong")
// fold[U](onOk: T => U, onErr: E => U): U
val foldedSuccess = successResult.fold(v => s"Value: $v", e => s"Error: $e") // "Value: 42"
val foldedFailure = failureResult.fold(v => s"Value: $v", e => s"Error: $e") // "Error: Something went wrong"
// withFilter[EE >: E](p: T => Boolean)(orElse: => EE): Result[T, EE]
val filteredTrueSuccess = successResult.withFilter(_ > 40)("Value too small") // Ok(42)
val filteredFalseSuccess = successResult.withFilter(_ > 100)("Value too small") // Err("Value too small")
val filteredFailure = failureResult.withFilter(_ > 100)("Value too small") // Err("Something went wrong")import resurge.*
@main def example(): Unit =
val successResult = Ok(42)
val failureResult = Err("Something went wrong")
// toOption: Option[T]
val successToOption = successResult.toOption // Some(42)
val failureToOption = failureResult.toOption // None
// toEither: Either[E, T]
val successToEither = successResult.toEither // Right(42)
val failureToEither = failureResult.toEither // Left("Something went wrong")import scala.util.{Failure, Success, Try}
import resurge.*
@main def example(): Unit =
// fromTry[T](t: Try[T]): Result[T, Throwable]
val successTry = Success(10)
val failureTry = Failure(new RuntimeException("Boom!"))
val fromSuccessTry = Result.fromTry(successTry) // Ok(10)
val fromFailureTry = Result.fromTry(failureTry) // Err(RuntimeException("Boom!"))If you would like to contribute or modify the library:
git clone https://github.com/Suopunki/Resurge
cd resurgesbt testsbt publishLocalModify the code and update tests as needed.
This project is licensed under the MIT License - see the LICENSE file for details.