From 7d3473855d0ac40e08fb5ae3fb6305483dd2fcfb Mon Sep 17 00:00:00 2001 From: Marco Garofalo Date: Tue, 20 Aug 2024 09:16:22 +0100 Subject: [PATCH] Introduce a way to early return on successful result with a null value --- .../dev/forkhandles/result4k/nullables.kt | 7 +++ .../dev/forkhandles/result4k/on_null_tests.kt | 43 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 result4k/core/src/test/kotlin/dev/forkhandles/result4k/on_null_tests.kt diff --git a/result4k/core/src/main/kotlin/dev/forkhandles/result4k/nullables.kt b/result4k/core/src/main/kotlin/dev/forkhandles/result4k/nullables.kt index 80d1fbb..e7ddd3f 100644 --- a/result4k/core/src/main/kotlin/dev/forkhandles/result4k/nullables.kt +++ b/result4k/core/src/main/kotlin/dev/forkhandles/result4k/nullables.kt @@ -33,3 +33,10 @@ fun Result.failureOrNull(): E? = when (this) { is Success -> null is Failure -> reason } + +/** + * Convert a `Success` of a nullable value to a `Success` of a non-null value, or calling `block` to abort from + * the current function if the value is `null` + */ +inline fun Result.onNull(block: () -> Nothing): Result = + flatMap { if (it != null) Success(it) else block() } diff --git a/result4k/core/src/test/kotlin/dev/forkhandles/result4k/on_null_tests.kt b/result4k/core/src/test/kotlin/dev/forkhandles/result4k/on_null_tests.kt new file mode 100644 index 0000000..da1f22d --- /dev/null +++ b/result4k/core/src/test/kotlin/dev/forkhandles/result4k/on_null_tests.kt @@ -0,0 +1,43 @@ +package dev.forkhandles.result4k + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class OnNullTests { + + @Test + fun `does nothing on successful non-null result`() { + fun subject() = Success("non-null") + .onNull { return Success("early-returned") } + + assertEquals(Success("non-null"), subject()) + } + + @Test + fun `does nothing on unsuccessful result`() { + fun subject() = resultFrom { throw AnError("kaboom"); "unreachable" } + .onNull { return Success("early-returned") } + + assertEquals(Failure(AnError("kaboom")), subject()) + } + + @Test + fun `early returns on successful null result`() { + fun subject() = Success(null) + .onNull { return Success("early-returned") } + .map { "mapped" } + + assertEquals(Success("early-returned"), subject()) + } + + @Test + fun `continue the chain on successful non-null result`() { + fun subject() = Success("non-null") + .onNull { return Success("early-returned") } + .map { "mapped" } + + assertEquals(Success("mapped"), subject()) + } +} + +private data class AnError(override val message: String) : Exception(message)