diff --git a/README.md b/README.md index fcfca3d..88ef13c 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,13 @@ As all functions are `inline` they can be used with suspending functions as well Also the following helpers exist: ```kotlin +isSuccess // property returning true if this instance represents a successful outcome, `false` otherwise. +isFailure // property returning true if this instance represents a failed outcome, `false` otherwise. successOrNull // property returning the success value if Success or null if Failure failureOrNull // property returning the failure value if Failure or null if Success onSuccess {} // executes given code block as side effect if Success and returns passed Either value unchanged onFailure {} // executes given code block as side effect if Failure and returns passed Either value unchanged +getOrElse {} // returns the encapsulated value if success or the result of the given code block Either.catch {} // executes the given code and returns its encapsulated result if invocation was successful and catching any exception that was thrown as a failure ``` diff --git a/build.gradle.kts b/build.gradle.kts index 9c46286..66c4b65 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ buildscript { allprojects { group = "net.grandcentrix.either" - version = "1.6" + version = "1.7" } } diff --git a/either/src/main/kotlin/net/grandcentrix/either/Either.kt b/either/src/main/kotlin/net/grandcentrix/either/Either.kt index e8f0e75..56a380d 100644 --- a/either/src/main/kotlin/net/grandcentrix/either/Either.kt +++ b/either/src/main/kotlin/net/grandcentrix/either/Either.kt @@ -69,6 +69,16 @@ sealed class Either { if (it is Failure) block(it.failure) } + /** + * Returns `true` if this instance represents a successful outcome, `false` otherwise. + */ + val isSuccess: Boolean get() = this is Success + + /** + * Returns `true` if this instance represents a failed outcome, `false` otherwise. + */ + val isFailure: Boolean get() = this is Failure + companion object { /** @@ -108,3 +118,12 @@ data class Success(val success: S) : Either() */ inline fun Either.flatMap(succeeded: (S1) -> Either): Either = fold({ this as Failure }, succeeded) + +/** + * Returns the encapsulated value if this instance represents [success][Either.isSuccess] or the + * result of [onFailure] function for the encapsulated [Failure] if it is [failure][Either.isFailure]. + * + * This function is a shorthand for `fold(failed = onFailure, succeeded = { it })` (see [fold]). + */ +inline fun Either.getOrElse(onFailure: (failure: F) -> S): S = + fold(failed = onFailure, succeeded = { it }) \ No newline at end of file diff --git a/either/src/test/kotlin/net/grandcentrix/either/EitherTest.kt b/either/src/test/kotlin/net/grandcentrix/either/EitherTest.kt index a4af663..1fddf5a 100644 --- a/either/src/test/kotlin/net/grandcentrix/either/EitherTest.kt +++ b/either/src/test/kotlin/net/grandcentrix/either/EitherTest.kt @@ -1,7 +1,7 @@ package net.grandcentrix.either import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Test import org.junit.jupiter.api.fail @@ -184,4 +184,38 @@ class EitherTest { val result = Either.catch { throw exception } assertThat(result).isEqualTo(Failure(exception)) } + + @Test + fun `when success then isSuccess returns true`() { + assertTrue(Success("success result").isSuccess) + } + + @Test + fun `when failure then isSuccess returns false`() { + assertFalse(Failure("failure result").isSuccess) + } + + @Test + fun `when success then isFailure returns false`() { + assertFalse(Success("success result").isFailure) + } + + @Test + fun `when failure then isFailure returns true`() { + assertTrue(Failure("failure result").isFailure) + } + + @Test + fun `when success then getOrElse returns success value`() { + val either: Either = Success("success") + val result = either.getOrElse { "else" } + assertThat(result).isEqualTo("success") + } + + @Test + fun `when failure then getOrElse returns else block`() { + val either: Either = Failure("failure result") + val result = either.getOrElse { "else" } + assertThat(result).isEqualTo("else") + } } \ No newline at end of file