Add Rust's mapOr & mapOrElse

See: https://blog.rust-lang.org/2020/01/30/Rust-1.41.0.html#library-changes
This commit is contained in:
Michael Bull 2020-01-31 09:17:49 +00:00
parent 434b8aa7fb
commit 43ebd5753a
2 changed files with 83 additions and 0 deletions

View File

@ -41,6 +41,43 @@ inline infix fun <V, E, F> Result<V, E>.mapError(transform: (E) -> F): Result<V,
} }
} }
/**
* Maps this [Result<V, E][Result] to [U] by either applying the [transform] function to the
* [value][Ok.value] if this [Result] is [Ok], or returning the [default] if this [Result] is an
* [Err].
*
* - Rust: [Result.map_or](https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or)
*/
inline fun <V, E, U> Result<V, E>.mapOr(default: U, transform: (V) -> U): U {
contract {
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
return when (this) {
is Ok -> transform(value)
is Err -> default
}
}
/**
* Maps this [Result<V, E>][Result] to [U] by applying either the [transform] function if this
* [Result] is [Ok], or the [default] function if this [Result] is an [Err]. Both of these
* functions must return the same type (`U`).
*
* - Rust: [Result.map_or_else](https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else)
*/
inline fun <V, E, U> Result<V, E>.mapOrElse(default: (E) -> U, transform: (V) -> U): U {
contract {
callsInPlace(default, InvocationKind.AT_MOST_ONCE)
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
return when (this) {
is Ok -> transform(value)
is Err -> default(error)
}
}
/** /**
* Returns a [Result<List<U>, E>][Result] containing the results of applying the given [transform] * Returns a [Result<List<U>, E>][Result] containing the results of applying the given [transform]
* function to each element in the original collection, returning early with the first [Err] if a * function to each element in the original collection, returning early with the first [Err] if a

View File

@ -66,6 +66,52 @@ class MapTest {
} }
} }
class MapOr {
@Test
fun returnsTransformedValueIfOk() {
val value = Ok("foo").mapOr(42, String::length)
assertEquals(
expected = 3,
actual = value
)
}
@Test
fun returnsDefaultValueIfErr() {
val value = Err("bar").mapOr(42, String::length)
assertEquals(
expected = 42,
actual = value
)
}
}
class MapOrElse {
private val k = 21
@Test
fun returnsTransformedValueIfOk() {
val value = Ok("foo").mapOrElse({ k * 2 }, String::length)
assertEquals(
expected = 3,
actual = value
)
}
@Test
fun returnsDefaultValueIfErr() {
val value = Err("bar").mapOrElse({ k * 2 }, String::length)
assertEquals(
expected = 42,
actual = value
)
}
}
class MapBoth { class MapBoth {
@Test @Test
@Suppress("UNREACHABLE_CODE") @Suppress("UNREACHABLE_CODE")