Michael Bull 2024-03-08 20:36:21 +00:00
parent f208f5ee79
commit 15fc1ff013
2 changed files with 58 additions and 0 deletions

View File

@ -22,6 +22,29 @@ public inline infix fun <V, E, U> Result<V, E>.map(transform: (V) -> U): Result<
}
}
/**
* Maps this [Result<V, Throwable>][Result] to [Result<U, Throwable>][Result] by either applying
* the [transform] function to the [value][Ok.value] if this [Result] is [Ok], or returning this
* [Err].
*
* This function catches any [Throwable] exception thrown by [transform] function and encapsulates
* it as a failure.
*
* - Elm: [Result.map](http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map)
* - Haskell: [Data.Bifunctor.first](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifunctor.html#v:first)
* - Rust: [Result.map](https://doc.rust-lang.org/std/result/enum.Result.html#method.map)
*/
public inline infix fun <V, U> Result<V, Throwable>.mapCatching(transform: (V) -> U): Result<U, Throwable> {
contract {
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
return when (this) {
is Ok -> runCatching { transform(value) }
is Err -> this
}
}
/**
* Maps this [Result<Result<V, E>, E>][Result] to [Result<V, E>][Result].
*

View File

@ -41,6 +41,41 @@ class MapTest {
}
}
class MapCatching {
private object MapException : Throwable()
@Test
fun returnsTransformedValueIfOk() {
val value: Result<Int, Throwable> = Ok(10)
assertEquals(
expected = Ok(30),
actual = value.mapCatching { it + 20 },
)
}
@Test
fun returnsErrIfTransformationThrows() {
val value: Result<Int, Throwable> = Ok(10)
assertEquals(
expected = Err(MapException),
actual = value.mapCatching { throw MapException },
)
}
@Test
fun returnsErrorIfErr() {
val value: Result<Int, Throwable> = Err(MapException)
assertEquals(
expected = Err(MapException),
actual = value.mapCatching { "hello $it" },
)
}
}
class Flatten {
@Test