Deprecate Ok/Err as return types
This is in preparation for the v2 release where these don't exist as types.
This commit is contained in:
parent
b19894a08c
commit
7ce7c16d7f
@ -1,8 +1,9 @@
|
||||
package com.github.michaelbull.result.coroutines
|
||||
|
||||
import com.github.michaelbull.result.Err
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.asErr
|
||||
import com.github.michaelbull.result.binding
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
@ -12,13 +13,31 @@ import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* Suspending variant of [binding][com.github.michaelbull.result.binding].
|
||||
* The suspendable [block] runs in a new [CoroutineScope], inheriting the parent [CoroutineContext].
|
||||
* This new scope is [cancelled][CoroutineScope.cancel] once a failing bind is encountered, eagerly cancelling all
|
||||
* child [jobs][Job].
|
||||
* Calls the specified function [block] with [CoroutineBindingScope] as its receiver and returns
|
||||
* its [Result].
|
||||
*
|
||||
* When inside a binding [block], the [bind][CoroutineBindingScope.bind] function is accessible on
|
||||
* any [Result]. Calling the [bind][CoroutineBindingScope.bind] function will attempt to unwrap the
|
||||
* [Result] and locally return its [value][Result.value].
|
||||
*
|
||||
* Unlike [binding], this function is designed for _concurrent decomposition_ of work. When any
|
||||
* [bind][CoroutineBindingScope.bind] returns an error, the [CoroutineScope] will be
|
||||
* [cancelled][Job.cancel], cancelling all the other children.
|
||||
*
|
||||
* This function returns as soon as the given [block] and all its child coroutines are completed.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* suspend fun provideX(): Result<Int, ExampleErr> { ... }
|
||||
* suspend fun provideY(): Result<Int, ExampleErr> { ... }
|
||||
*
|
||||
* val result: Result<Int, ExampleErr> = coroutineBinding {
|
||||
* val x = async { provideX().bind() }
|
||||
* val y = async { provideY().bind() }
|
||||
* x.await() + y.await()
|
||||
* }
|
||||
*/
|
||||
public suspend inline fun <V, E> coroutineBinding(crossinline block: suspend CoroutineBindingScope<E>.() -> V): Result<V, E> {
|
||||
contract {
|
||||
@ -55,11 +74,12 @@ internal class CoroutineBindingScopeImpl<E>(
|
||||
var result: Result<Nothing, E>? = null
|
||||
|
||||
override suspend fun <V> Result<V, E>.bind(): V {
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> mutex.withLock {
|
||||
return if (isOk) {
|
||||
value
|
||||
} else {
|
||||
mutex.withLock {
|
||||
if (result == null) {
|
||||
result = this
|
||||
result = this.asErr()
|
||||
coroutineContext.cancel(BindCancellationException)
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,14 @@ import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Returns [result] if this [Result] is [Ok], otherwise this [Err].
|
||||
* Returns [result] if this result [is ok][Result.isOk], otherwise [this].
|
||||
*
|
||||
* - Rust: [Result.and](https://doc.rust-lang.org/std/result/enum.Result.html#method.and)
|
||||
*/
|
||||
public infix fun <V, E, U> Result<V, E>.and(result: Result<U, E>): Result<U, E> {
|
||||
return when (this) {
|
||||
is Ok -> result
|
||||
is Err -> this
|
||||
return when {
|
||||
isOk -> result
|
||||
else -> this.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ public inline infix fun <V, E, U> Result<V, E>.and(result: () -> Result<U, E>):
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [Result<U, E>][Result] by either applying the [transform]
|
||||
* function if this [Result] is [Ok], or returning this [Err].
|
||||
* function if this result [is ok][Result.isOk], or returning [this].
|
||||
*
|
||||
* - Elm: [Result.andThen](http://package.elm-lang.org/packages/elm-lang/core/latest/Result#andThen)
|
||||
* - Rust: [Result.and_then](https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then)
|
||||
@ -36,8 +36,8 @@ public inline infix fun <V, E, U> Result<V, E>.andThen(transform: (V) -> Result<
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> transform(value)
|
||||
is Err -> this
|
||||
return when {
|
||||
isOk -> transform(value)
|
||||
else -> this.asErr()
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,14 @@ import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Calls the specified function [block] with [BindingScope] as its receiver and returns its [Result].
|
||||
* Calls the specified function [block] with [BindingScope] as its receiver and returns its
|
||||
* [Result].
|
||||
*
|
||||
* When inside a [binding] block, the [bind][BindingScope.bind] function is accessible on any [Result]. Calling the
|
||||
* [bind][BindingScope.bind] function will attempt to unwrap the [Result] and locally return its [value][Ok.value]. If
|
||||
* the [Result] is an [Err], the binding block will terminate with that bind and return that failed-to-bind [Err].
|
||||
* When inside a binding [block], the [bind][BindingScope.bind] function is accessible on any
|
||||
* [Result]. Calling the [bind][BindingScope.bind] function will attempt to unwrap the [Result]
|
||||
* and locally return its [value][Result.value].
|
||||
*
|
||||
* If a [bind][BindingScope.bind] returns an error, the [block] will terminate immediately.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
@ -54,12 +57,11 @@ internal class BindingScopeImpl<E> : BindingScope<E> {
|
||||
var result: Result<Nothing, E>? = null
|
||||
|
||||
override fun <V> Result<V, E>.bind(): V {
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> {
|
||||
this@BindingScopeImpl.result = this
|
||||
throw BindException
|
||||
}
|
||||
return if (isOk) {
|
||||
value
|
||||
} else {
|
||||
result = this.asErr()
|
||||
throw BindException
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Returns the [value][Ok.value] if this [Result] is [Ok], otherwise `null`.
|
||||
* Returns the [value][Result.value] if this result [is ok][Result.isOk], otherwise `null`.
|
||||
*
|
||||
* - Elm: [Result.toMaybe](http://package.elm-lang.org/packages/elm-lang/core/latest/Result#toMaybe)
|
||||
* - Rust: [Result.ok](https://doc.rust-lang.org/std/result/enum.Result.html#method.ok)
|
||||
@ -15,14 +15,14 @@ public fun <V, E> Result<V, E>.get(): V? {
|
||||
returns(null) implies (this@get is Err<E>)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> null
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [error][Err.error] if this [Result] is [Err], otherwise `null`.
|
||||
* Returns the [error][Result.error] if this result [is an error][Result.isErr], otherwise `null`.
|
||||
*
|
||||
* - Rust: [Result.err](https://doc.rust-lang.org/std/result/enum.Result.html#method.err)
|
||||
*/
|
||||
@ -32,26 +32,26 @@ public fun <V, E> Result<V, E>.getError(): E? {
|
||||
returnsNotNull() implies (this@getError is Err<E>)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> null
|
||||
is Err -> error
|
||||
return when {
|
||||
isErr -> error
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [value][Ok.value] if this [Result] is [Ok], otherwise [default].
|
||||
* Returns the [value][Result.value] if this result [is ok][Result.isOk], otherwise [default].
|
||||
*
|
||||
* - Elm: [Result.withDefault](http://package.elm-lang.org/packages/elm-lang/core/latest/Result#withDefault)
|
||||
* - Haskell: [Result.fromLeft](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:fromLeft)
|
||||
* - Rust: [Result.unwrap_or](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or)
|
||||
*
|
||||
* @param default The value to return if [Err].
|
||||
* @return The [value][Ok.value] if [Ok], otherwise [default].
|
||||
* @return The [value][Result.value] if [Ok], otherwise [default].
|
||||
*/
|
||||
public infix fun <V, E> Result<V, E>.getOr(default: V): V {
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> default
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> default
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,17 +65,18 @@ public inline infix fun <V, E> Result<V, E>.getOr(default: () -> V): V {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [error][Err.error] if this [Result] is [Err], otherwise [default].
|
||||
* Returns the [error][Result.error] if this result [is an error][Result.isErr], otherwise
|
||||
* [default].
|
||||
*
|
||||
* - Haskell: [Result.fromRight](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:fromRight)
|
||||
*
|
||||
* @param default The error to return if [Ok].
|
||||
* @return The [error][Err.error] if [Err], otherwise [default].
|
||||
* @return The [error][Result.error] if [Err], otherwise [default].
|
||||
*/
|
||||
public infix fun <V, E> Result<V, E>.getErrorOr(default: E): E {
|
||||
return when (this) {
|
||||
is Ok -> default
|
||||
is Err -> error
|
||||
return when {
|
||||
isOk -> default
|
||||
else -> error
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,8 +90,8 @@ public inline infix fun <V, E> Result<V, E>.getErrorOr(default: () -> E): E {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [value][Ok.value] if this [Result] is [Ok], otherwise the
|
||||
* [transformation][transform] of the [error][Err.error].
|
||||
* Returns the [value][Result.value] if this result [is ok][Result.isOk], otherwise the
|
||||
* [transformation][transform] of the [error][Result.error].
|
||||
*
|
||||
* - Elm: [Result.extract](http://package.elm-lang.org/packages/elm-community/result-extra/2.2.0/Result-Extra#extract)
|
||||
* - Rust: [Result.unwrap_or_else](https://doc.rust-lang.org/src/core/result.rs.html#735-740)
|
||||
@ -100,30 +101,30 @@ public inline infix fun <V, E> Result<V, E>.getOrElse(transform: (E) -> V): V {
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> transform(error)
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> transform(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [error][Err.error] if this [Result] is [Err], otherwise the
|
||||
* [transformation][transform] of the [value][Ok.value].
|
||||
* Returns the [error][Result.error] if this result [is an error][Result.isErr], otherwise the
|
||||
* [transformation][transform] of the [value][Result.value].
|
||||
*/
|
||||
public inline infix fun <V, E> Result<V, E>.getErrorOrElse(transform: (V) -> E): E {
|
||||
contract {
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> transform(value)
|
||||
is Err -> error
|
||||
return when {
|
||||
isErr -> error
|
||||
else -> transform(value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [value][Ok.value] if this [Result] is [Ok], otherwise throws the
|
||||
* [error][Err.error].
|
||||
* Returns the [value][Result.value] if this result [is ok][Result.isOk], otherwise throws the
|
||||
* [error][Result.error].
|
||||
*
|
||||
* This is functionally equivalent to [`getOrElse { throw it }`][getOrElse].
|
||||
*/
|
||||
@ -132,15 +133,15 @@ public fun <V, E : Throwable> Result<V, E>.getOrThrow(): V {
|
||||
returns() implies (this@getOrThrow is Ok<V>)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> throw error
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [value][Ok.value] if this [Result] is [Ok], otherwise throws the
|
||||
* [transformation][transform] of the [error][Err.error] to a [Throwable].
|
||||
* Returns the [value][Result.value] if this result [is ok][Result.isOk], otherwise throws the
|
||||
* [transformation][transform] of the [error][Result.error] to a [Throwable].
|
||||
*/
|
||||
public inline infix fun <V, E> Result<V, E>.getOrThrow(transform: (E) -> Throwable): V {
|
||||
contract {
|
||||
@ -148,21 +149,21 @@ public inline infix fun <V, E> Result<V, E>.getOrThrow(transform: (E) -> Throwab
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> throw transform(error)
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> throw transform(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges this [Result<V, E>][Result] to [U], returning the [value][Ok.value] if this [Result] is [Ok], otherwise the
|
||||
* [error][Err.error].
|
||||
* Merges this [Result<V, E>][Result] to [U], returning the [value][Result.value] if this result
|
||||
* [is ok][Result.isOk], otherwise the [error][Result.error].
|
||||
*
|
||||
* - Scala: [MergeableEither.merge](https://www.scala-lang.org/api/2.12.0/scala/util/Either$$MergeableEither.html#merge:A)
|
||||
*/
|
||||
public fun <V : U, E : U, U> Result<V, E>.merge(): U {
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> error
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> error
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,26 @@
|
||||
package com.github.michaelbull.result
|
||||
|
||||
/**
|
||||
* Returns a list containing only elements that are [Ok].
|
||||
* Returns a list containing only elements that [are ok][Result.isOk].
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.filterValues(): List<V> {
|
||||
return filterValuesTo(ArrayList())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing only elements that are [Err].
|
||||
* Returns a list containing only elements that [are an error][Result.isErr].
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.filterErrors(): List<E> {
|
||||
return filterErrorsTo(ArrayList())
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the [values][Ok.value] of each element that is [Ok] to the given [destination].
|
||||
* Appends the [values][Result.value] of each element that [is ok][Result.isOk] to the given
|
||||
* [destination].
|
||||
*/
|
||||
public fun <V, E, C : MutableCollection<in V>> Iterable<Result<V, E>>.filterValuesTo(destination: C): C {
|
||||
for (element in this) {
|
||||
if (element is Ok<V>) {
|
||||
if (element.isOk) {
|
||||
destination.add(element.value)
|
||||
}
|
||||
}
|
||||
@ -28,11 +29,12 @@ public fun <V, E, C : MutableCollection<in V>> Iterable<Result<V, E>>.filterValu
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the [errors][Err.error] of each element that is [Err] to the given [destination].
|
||||
* Appends the [errors][Result.error] of each element that [is an error][Result.isErr] to the given
|
||||
* [destination].
|
||||
*/
|
||||
public fun <V, E, C : MutableCollection<in E>> Iterable<Result<V, E>>.filterErrorsTo(destination: C): C {
|
||||
for (element in this) {
|
||||
if (element is Err<E>) {
|
||||
if (element.isErr) {
|
||||
destination.add(element.error)
|
||||
}
|
||||
}
|
||||
@ -41,45 +43,45 @@ public fun <V, E, C : MutableCollection<in E>> Iterable<Result<V, E>>.filterErro
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if each element is [Ok], `false` otherwise.
|
||||
* Returns `true` if each element [is ok][Result.isOk], `false` otherwise.
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.allOk(): Boolean {
|
||||
return all { it is Ok }
|
||||
return all(Result<V, E>::isOk)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if each element is [Err], `false` otherwise.
|
||||
* Returns `true` if each element [is an error][Result.isErr], `false` otherwise.
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.allErr(): Boolean {
|
||||
return all { it is Err }
|
||||
return all(Result<V, E>::isErr)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if at least one element is [Ok], `false` otherwise.
|
||||
* Returns `true` if at least one element [is ok][Result.isOk], `false` otherwise.
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.anyOk(): Boolean {
|
||||
return any { it is Ok }
|
||||
return any(Result<V, E>::isOk)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if at least one element is [Err], `false` otherwise.
|
||||
* Returns `true` if at least one element [is an error][Result.isErr], `false` otherwise.
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.anyErr(): Boolean {
|
||||
return any { it is Err }
|
||||
return any(Result<V, E>::isErr)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements that are [Ok].
|
||||
* Returns the number of elements that [are ok][Result.isOk].
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.countOk(): Int {
|
||||
return count { it is Ok }
|
||||
return count(Result<V, E>::isOk)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements that are [Err].
|
||||
* Returns the number of elements that [are an error][Result.isErr].
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.countErr(): Int {
|
||||
return count { it is Err }
|
||||
return count(Result<V, E>::isErr)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,9 +95,11 @@ public inline fun <T, R, E> Iterable<T>.fold(
|
||||
var accumulator = initial
|
||||
|
||||
for (element in this) {
|
||||
accumulator = when (val result = operation(accumulator, element)) {
|
||||
is Ok -> result.value
|
||||
is Err -> return Err(result.error)
|
||||
val result = operation(accumulator, element)
|
||||
|
||||
accumulator = when {
|
||||
result.isOk -> result.value
|
||||
else -> return Err(result.error)
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,7 +110,7 @@ public inline fun <T, R, E> Iterable<T>.fold(
|
||||
* Accumulates value starting with [initial] value and applying [operation] from right to left to
|
||||
* each element and current accumulator value.
|
||||
*/
|
||||
public inline fun <T, R, E, C : Result<R, E>> List<T>.foldRight(
|
||||
public inline fun <T, R, E> List<T>.foldRight(
|
||||
initial: R,
|
||||
operation: (T, acc: R) -> Result<R, E>,
|
||||
): Result<R, E> {
|
||||
@ -116,9 +120,11 @@ public inline fun <T, R, E, C : Result<R, E>> List<T>.foldRight(
|
||||
val iterator = listIterator(size)
|
||||
|
||||
while (iterator.hasPrevious()) {
|
||||
accumulator = when (val result = operation(iterator.previous(), accumulator)) {
|
||||
is Ok -> result.value
|
||||
is Err -> return Err(result.error)
|
||||
val result = operation(iterator.previous(), accumulator)
|
||||
|
||||
accumulator = when {
|
||||
result.isOk -> result.value
|
||||
else -> return Err(result.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -127,8 +133,8 @@ public inline fun <T, R, E, C : Result<R, E>> List<T>.foldRight(
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a vararg of [Results][Result] into a single [Result] (holding a [List]). Elements in the returned list
|
||||
* are in the same order is the input vararg.
|
||||
* Combines the specified [results] into a single [Result] (holding a [List]). Elements in the
|
||||
* returned list are in the same order as the specified [results].
|
||||
*
|
||||
* - Elm: [Result.Extra.combine](http://package.elm-lang.org/packages/elm-community/result-extra/2.2.0/Result-Extra#combine)
|
||||
*/
|
||||
@ -137,16 +143,16 @@ public fun <V, E, R : Result<V, E>> combine(vararg results: R): Result<List<V>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines an [Iterable] of [Results][Result] into a single [Result] (holding a [List]). Elements in the returned
|
||||
* list are in the input [Iterable] order.
|
||||
* Combines [this] iterable into a single [Result] (holding a [List]). Elements in the returned
|
||||
* list are in the the same order as [this].
|
||||
*
|
||||
* - Elm: [Result.Extra.combine](http://package.elm-lang.org/packages/elm-community/result-extra/2.2.0/Result-Extra#combine)
|
||||
*/
|
||||
public fun <V, E> Iterable<Result<V, E>>.combine(): Result<List<V>, E> {
|
||||
val values = map {
|
||||
when (it) {
|
||||
is Ok -> it.value
|
||||
is Err -> return it
|
||||
val values = map { result ->
|
||||
when {
|
||||
result.isOk -> result.value
|
||||
else -> return result.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,8 +160,9 @@ public fun <V, E> Iterable<Result<V, E>>.combine(): Result<List<V>, E> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts from a vararg of [Results][Result] all the [Ok] elements. All the [Ok] elements are
|
||||
* extracted in order.
|
||||
* Returns a [List] containing the [value][Result.value] of each element in the specified [results]
|
||||
* that [is ok][Result.isOk]. Elements in the returned list are in the same order as the specified
|
||||
* [results].
|
||||
*
|
||||
* - Haskell: [Data.Either.lefts](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:lefts)
|
||||
*/
|
||||
@ -178,8 +185,9 @@ public fun <V, E> Iterable<Result<V, E>>.getAll(): List<V> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts from a vararg of [Results][Result] all the [Err] elements. All the [Err] elements are
|
||||
* extracted in order.
|
||||
* Returns a [List] containing the [error][Result.error] of each element in the specified [results]
|
||||
* that [is an error][Result.isErr]. Elements in the returned list are in the same order as the
|
||||
* specified [results].
|
||||
*
|
||||
* - Haskell: [Data.Either.rights](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:rights)
|
||||
*/
|
||||
@ -202,9 +210,9 @@ public fun <V, E> Iterable<Result<V, E>>.getAllErrors(): List<E> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Partitions a vararg of [Results][Result] into a [Pair] of [Lists][List]. All the [Ok] elements
|
||||
* are extracted, in order, to the [first][Pair.first] value. Similarly the [Err] elements are
|
||||
* extracted to the [Pair.second] value.
|
||||
* Partitions the specified [results] into a [Pair] of [Lists][List]. An element that
|
||||
* [is ok][Result.isOk] will appear in the [first][Pair.first] list, whereas an element that
|
||||
* [is an error][Result.isErr] will appear in the [second][Pair.second] list.
|
||||
*
|
||||
* - Haskell: [Data.Either.partitionEithers](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:partitionEithers)
|
||||
*/
|
||||
@ -213,9 +221,10 @@ public fun <V, E, R : Result<V, E>> partition(vararg results: R): Pair<List<V>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Partitions an [Iterable] of [Results][Result] into a [Pair] of [Lists][List]. All the [Ok]
|
||||
* elements are extracted, in order, to the [first][Pair.first] value. Similarly the [Err] elements
|
||||
* are extracted to the [Pair.second] value.
|
||||
*
|
||||
* Partitions this into a [Pair] of [Lists][List]. An element that [is ok][Result.isOk] will appear
|
||||
* in the [first][Pair.first] list, whereas an element that [is an error][Result.isErr] will appear
|
||||
* in the [second][Pair.second] list.
|
||||
*
|
||||
* - Haskell: [Data.Either.partitionEithers](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:partitionEithers)
|
||||
*/
|
||||
@ -223,10 +232,11 @@ public fun <V, E> Iterable<Result<V, E>>.partition(): Pair<List<V>, List<E>> {
|
||||
val values = mutableListOf<V>()
|
||||
val errors = mutableListOf<E>()
|
||||
|
||||
forEach { result ->
|
||||
when (result) {
|
||||
is Ok -> values.add(result.value)
|
||||
is Err -> errors.add(result.error)
|
||||
for (result in this) {
|
||||
if (result.isOk) {
|
||||
values += result.value
|
||||
} else {
|
||||
errors += result.error
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,15 +246,17 @@ public fun <V, E> Iterable<Result<V, E>>.partition(): Pair<List<V>, List<E>> {
|
||||
/**
|
||||
* 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
|
||||
* transformation fails. Elements in the returned list are in the input [Iterable] order.
|
||||
* transformation fails. Elements in the returned list are in the same order as [this].
|
||||
*/
|
||||
public inline fun <V, E, U> Iterable<V>.mapResult(
|
||||
transform: (V) -> Result<U, E>,
|
||||
): Result<List<U>, E> {
|
||||
val values = map { element ->
|
||||
when (val transformed = transform(element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
val transformed = transform(element)
|
||||
|
||||
when {
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,16 +266,18 @@ public inline fun <V, E, U> Iterable<V>.mapResult(
|
||||
/**
|
||||
* Applies the given [transform] function to each element of the original collection and appends
|
||||
* the results to the given [destination], returning early with the first [Err] if a
|
||||
* transformation fails. Elements in the returned list are in the input [Iterable] order.
|
||||
* transformation fails. Elements in the returned list are in the same order as [this].
|
||||
*/
|
||||
public inline fun <V, E, U, C : MutableCollection<in U>> Iterable<V>.mapResultTo(
|
||||
destination: C,
|
||||
transform: (V) -> Result<U, E>,
|
||||
): Result<C, E> {
|
||||
val values = mapTo(destination) { element ->
|
||||
when (val transformed = transform(element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
val transformed = transform(element)
|
||||
|
||||
when {
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,17 +287,19 @@ public inline fun <V, E, U, C : MutableCollection<in U>> Iterable<V>.mapResultTo
|
||||
/**
|
||||
* Returns a [Result<List<U>, E>][Result] containing only the non-null results of applying the
|
||||
* given [transform] function to each element in the original collection, returning early with the
|
||||
* first [Err] if a transformation fails. Elements in the returned list are in the input [Iterable]
|
||||
* order.
|
||||
* first [Err] if a transformation fails. Elements in the returned list are in the same order as
|
||||
* [this].
|
||||
*/
|
||||
public inline fun <V, E, U : Any> Iterable<V>.mapResultNotNull(
|
||||
transform: (V) -> Result<U, E>?,
|
||||
): Result<List<U>, E> {
|
||||
val values = mapNotNull { element ->
|
||||
when (val transformed = transform(element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
null -> null
|
||||
val transformed = transform(element)
|
||||
|
||||
when {
|
||||
transformed == null -> null
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,10 +316,12 @@ public inline fun <V, E, U : Any, C : MutableCollection<in U>> Iterable<V>.mapRe
|
||||
transform: (V) -> Result<U, E>?,
|
||||
): Result<C, E> {
|
||||
val values = mapNotNullTo(destination) { element ->
|
||||
when (val transformed = transform(element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
null -> null
|
||||
val transformed = transform(element)
|
||||
|
||||
when {
|
||||
transformed == null -> null
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,16 +331,18 @@ public inline fun <V, E, U : Any, C : MutableCollection<in U>> Iterable<V>.mapRe
|
||||
/**
|
||||
* Returns a [Result<List<U>, E>][Result] containing the results of applying the given [transform]
|
||||
* function to each element and its index in the original collection, returning early with the
|
||||
* first [Err] if a transformation fails. Elements in the returned list are in the input [Iterable]
|
||||
* order.
|
||||
* first [Err] if a transformation fails. Elements in the returned list are in same order as
|
||||
* [this].
|
||||
*/
|
||||
public inline fun <V, E, U> Iterable<V>.mapResultIndexed(
|
||||
transform: (index: Int, V) -> Result<U, E>,
|
||||
): Result<List<U>, E> {
|
||||
val values = mapIndexed { index, element ->
|
||||
when (val transformed = transform(index, element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
val transformed = transform(index, element)
|
||||
|
||||
when {
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,9 +359,11 @@ public inline fun <V, E, U, C : MutableCollection<in U>> Iterable<V>.mapResultIn
|
||||
transform: (index: Int, V) -> Result<U, E>,
|
||||
): Result<C, E> {
|
||||
val values = mapIndexedTo(destination) { index, element ->
|
||||
when (val transformed = transform(index, element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
val transformed = transform(index, element)
|
||||
|
||||
when {
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,16 +374,18 @@ public inline fun <V, E, U, C : MutableCollection<in U>> Iterable<V>.mapResultIn
|
||||
* Returns a [Result<List<U>, E>][Result] containing only the non-null results of applying the
|
||||
* given [transform] function to each element and its index in the original collection, returning
|
||||
* early with the first [Err] if a transformation fails. Elements in the returned list are in
|
||||
* the input [Iterable] order.
|
||||
* the same order as [this].
|
||||
*/
|
||||
public inline fun <V, E, U : Any> Iterable<V>.mapResultIndexedNotNull(
|
||||
transform: (index: Int, V) -> Result<U, E>?,
|
||||
): Result<List<U>, E> {
|
||||
val values = mapIndexedNotNull { index, element ->
|
||||
when (val transformed = transform(index, element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
null -> null
|
||||
val transformed = transform(index, element)
|
||||
|
||||
when {
|
||||
transformed == null -> null
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,10 +402,12 @@ public inline fun <V, E, U : Any, C : MutableCollection<in U>> Iterable<V>.mapRe
|
||||
transform: (index: Int, V) -> Result<U, E>?,
|
||||
): Result<C, E> {
|
||||
val values = mapIndexedNotNullTo(destination) { index, element ->
|
||||
when (val transformed = transform(index, element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
null -> null
|
||||
val transformed = transform(index, element)
|
||||
|
||||
when {
|
||||
transformed == null -> null
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [Result<U, E>][Result] by either applying the [transform]
|
||||
* function to the [value][Ok.value] if this [Result] is [Ok], or returning this [Err].
|
||||
* function to the [value][Result.value] if this result [is ok][Result.isOk], or returning [this].
|
||||
*
|
||||
* - 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)
|
||||
@ -16,19 +16,19 @@ public inline infix fun <V, E, U> Result<V, E>.map(transform: (V) -> U): Result<
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> Ok(transform(value))
|
||||
is Err -> this
|
||||
return when {
|
||||
isOk -> Ok(transform(value))
|
||||
else -> this.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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].
|
||||
* the [transform] function to the [value][Result.value] if this result [is ok][Result.isOk], or
|
||||
* returning [this].
|
||||
*
|
||||
* This function catches any [Throwable] exception thrown by [transform] function and encapsulates
|
||||
* it as a failure.
|
||||
* it as an [Err].
|
||||
*
|
||||
* - 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)
|
||||
@ -39,9 +39,9 @@ public inline infix fun <V, U> Result<V, Throwable>.mapCatching(transform: (V) -
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> runCatching { transform(value) }
|
||||
is Err -> this
|
||||
return when {
|
||||
isOk -> runCatching { transform(value) }
|
||||
else -> this.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,14 +53,10 @@ public inline infix fun <V, U> Result<V, Throwable>.mapCatching(transform: (V) -
|
||||
* - Rust: [Result.transpose][https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose]
|
||||
*/
|
||||
public inline fun <V, E> Result<V?, E>.transpose(): Result<V, E>? {
|
||||
return when (this) {
|
||||
is Ok -> if (value == null) {
|
||||
null
|
||||
} else {
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
is Err -> this
|
||||
return when {
|
||||
isOk && value == null -> null
|
||||
isOk && value != null -> this.asOk()
|
||||
else -> this.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,16 +65,16 @@ public inline fun <V, E> Result<V?, E>.transpose(): Result<V, E>? {
|
||||
*
|
||||
* - Rust: [Result.flatten](https://doc.rust-lang.org/std/result/enum.Result.html#method.flatten)
|
||||
*/
|
||||
public inline fun <V, E> Result<Result<V, E>, E>.flatten(): Result<V, E> {
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> this
|
||||
public fun <V, E> Result<Result<V, E>, E>.flatten(): Result<V, E> {
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> this.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [Result<U, E>][Result] by either applying the [transform]
|
||||
* function if this [Result] is [Ok], or returning this [Err].
|
||||
* function if this result [is ok][Result.isOk], or returning [this].
|
||||
*
|
||||
* This is functionally equivalent to [andThen].
|
||||
*
|
||||
@ -94,7 +90,8 @@ public inline infix fun <V, E, U> Result<V, E>.flatMap(transform: (V) -> Result<
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [U] by applying either the [success] function if this
|
||||
* [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||
* result [is ok][Result.isOk], or the [failure] function if this result
|
||||
* [is an error][Result.isErr].
|
||||
*
|
||||
* Unlike [mapEither], [success] and [failure] must both return [U].
|
||||
*
|
||||
@ -110,15 +107,16 @@ public inline fun <V, E, U> Result<V, E>.mapBoth(
|
||||
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> success(value)
|
||||
is Err -> failure(error)
|
||||
return when {
|
||||
isOk -> success(value)
|
||||
else -> failure(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [U] by applying either the [success] function if this
|
||||
* [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||
* result [is ok][Result.isOk], or the [failure] function if this result
|
||||
* [is an error][Result.isErr].
|
||||
*
|
||||
* Unlike [mapEither], [success] and [failure] must both return [U].
|
||||
*
|
||||
@ -141,7 +139,8 @@ public inline fun <V, E, U> Result<V, E>.fold(
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [Result<U, E>][Result] by applying either the [success]
|
||||
* function if this [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||
* function if this result [is ok][Result.isOk], or the [failure] function if this result
|
||||
* [is an error][Result.isErr].
|
||||
*
|
||||
* Unlike [mapEither], [success] and [failure] must both return [U].
|
||||
*
|
||||
@ -157,15 +156,16 @@ public inline fun <V, E, U> Result<V, E>.flatMapBoth(
|
||||
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> success(value)
|
||||
is Err -> failure(error)
|
||||
return when {
|
||||
isOk -> success(value)
|
||||
else -> failure(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [Result<U, F>][Result] by applying either the [success]
|
||||
* function if this [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||
* function if this result [is ok][Result.isOk], or the [failure] function if this result
|
||||
* [is an error][Result.isErr].
|
||||
*
|
||||
* Unlike [mapBoth], [success] and [failure] may either return [U] or [F] respectively.
|
||||
*
|
||||
@ -180,15 +180,16 @@ public inline fun <V, E, U, F> Result<V, E>.mapEither(
|
||||
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> Ok(success(value))
|
||||
is Err -> Err(failure(error))
|
||||
return when {
|
||||
isOk -> Ok(success(value))
|
||||
else -> Err(failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [Result<U, F>][Result] by applying either the [success]
|
||||
* function if this [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||
* function if this result [is ok][Result.isOk], or the [failure] function if this result
|
||||
* [is an error][Result.isErr].
|
||||
*
|
||||
* Unlike [mapBoth], [success] and [failure] may either return [U] or [F] respectively.
|
||||
*
|
||||
@ -203,15 +204,16 @@ public inline fun <V, E, U, F> Result<V, E>.flatMapEither(
|
||||
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> success(value)
|
||||
is Err -> failure(error)
|
||||
return when {
|
||||
isOk -> success(value)
|
||||
else -> failure(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps this [Result<V, E>][Result] to [Result<V, F>][Result] by either applying the [transform]
|
||||
* function to the [error][Err.error] if this [Result] is [Err], or returning this [Ok].
|
||||
* function to the [error][Result.error] if this result [is an error][Result.isErr], or returning
|
||||
* [this].
|
||||
*
|
||||
* - Elm: [Result.mapError](http://package.elm-lang.org/packages/elm-lang/core/latest/Result#mapError)
|
||||
* - Haskell: [Data.Bifunctor.right](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifunctor.html#v:second)
|
||||
@ -222,46 +224,52 @@ public inline infix fun <V, E, F> Result<V, E>.mapError(transform: (E) -> F): Re
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> Err(transform(error))
|
||||
return when {
|
||||
isErr -> Err(transform(error))
|
||||
else -> this.asOk()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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].
|
||||
* [value][Result.value] if this result [is ok][Result.isOk], or returning the [default] if this
|
||||
* result [is an error][Result.isErr].
|
||||
*
|
||||
* - Rust: [Result.map_or](https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or)
|
||||
*/
|
||||
public inline fun <V, E, U> Result<V, E>.mapOr(default: U, transform: (V) -> U): U {
|
||||
public 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
|
||||
return when {
|
||||
isOk -> transform(value)
|
||||
else -> 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]).
|
||||
* result [is ok][Result.isOk], or the [default] function if this result
|
||||
* [is an error][Result.isErr]. 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)
|
||||
*/
|
||||
public inline fun <V, E, U> Result<V, E>.mapOrElse(default: (E) -> U, transform: (V) -> U): U {
|
||||
public 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)
|
||||
return when {
|
||||
isOk -> transform(value)
|
||||
else -> default(error)
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,35 +281,40 @@ public inline fun <V, E, U> Result<V, E>.mapOrElse(default: (E) -> U, transform:
|
||||
public inline infix fun <V, E, U> Result<Iterable<V>, E>.mapAll(transform: (V) -> Result<U, E>): Result<List<U>, E> {
|
||||
return map { iterable ->
|
||||
iterable.map { element ->
|
||||
when (val transformed = transform(element)) {
|
||||
is Ok -> transformed.value
|
||||
is Err -> return transformed
|
||||
val transformed = transform(element)
|
||||
|
||||
when {
|
||||
transformed.isOk -> transformed.value
|
||||
else -> return transformed.asErr()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [value][Ok.value] if this [Result] is [Ok]
|
||||
* and satisfies the given [predicate], otherwise this [Result].
|
||||
* Returns the [transformation][transform] of the [value][Result.value] if this result
|
||||
* [is ok][Result.isOk] and satisfies the given [predicate], otherwise [this].
|
||||
*
|
||||
* @see [takeIf]
|
||||
*/
|
||||
public inline fun <V, E> Result<V, E>.toErrorIf(predicate: (V) -> Boolean, transform: (V) -> E): Result<V, E> {
|
||||
public inline fun <V, E> Result<V, E>.toErrorIf(
|
||||
predicate: (V) -> Boolean,
|
||||
transform: (V) -> E,
|
||||
): Result<V, E> {
|
||||
contract {
|
||||
callsInPlace(predicate, InvocationKind.AT_MOST_ONCE)
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when {
|
||||
this is Ok && predicate(value) -> Err(transform(value))
|
||||
isOk && predicate(value) -> Err(transform(value))
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supplied [error] if this [Result] is [Ok] and the [value][Ok.value] is `null`,
|
||||
* otherwise this [Result].
|
||||
* Returns the supplied [error] if this result [is ok][Result.isOk] and the [value][Result.value]
|
||||
* is `null`, otherwise [this].
|
||||
*
|
||||
* @see [toErrorIf]
|
||||
*/
|
||||
@ -310,43 +323,37 @@ public inline fun <V, E> Result<V?, E>.toErrorIfNull(error: () -> E): Result<V,
|
||||
callsInPlace(error, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> if (value == null) {
|
||||
Err(error())
|
||||
} else {
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
is Err -> this
|
||||
return when {
|
||||
isOk && value == null -> Err(error())
|
||||
isOk && value != null -> this.asOk()
|
||||
else -> this.asErr()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [value][Ok.value] if this [Result] is [Ok]
|
||||
* and _does not_ satisfy the given [predicate], otherwise this [Result].
|
||||
* Returns the [transformation][transform] of the [value][Result.value] if this result
|
||||
* [is ok][Result.isOk] and _does not_ satisfy the given [predicate], otherwise [this].
|
||||
*
|
||||
* @see [takeUnless]
|
||||
*/
|
||||
public inline fun <V, E> Result<V, E>.toErrorUnless(predicate: (V) -> Boolean, transform: (V) -> E): Result<V, E> {
|
||||
public inline fun <V, E> Result<V, E>.toErrorUnless(
|
||||
predicate: (V) -> Boolean,
|
||||
transform: (V) -> E,
|
||||
): Result<V, E> {
|
||||
contract {
|
||||
callsInPlace(predicate, InvocationKind.AT_MOST_ONCE)
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> if (!predicate(value)) {
|
||||
Err(transform(value))
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
is Err -> this
|
||||
return when {
|
||||
isOk && !predicate(value) -> Err(transform(value))
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supplied [error] unless this [Result] is [Ok] and the [value][Ok.value] is `null`,
|
||||
* otherwise this [Result].
|
||||
* Returns the supplied [error] unless this result [is ok][Result.isOk] and the
|
||||
* [value][Result.value] is `null`, otherwise [this].
|
||||
*
|
||||
* @see [toErrorUnless]
|
||||
*/
|
||||
@ -355,13 +362,8 @@ public inline fun <V, E> Result<V, E>.toErrorUnlessNull(error: () -> E): Result<
|
||||
callsInPlace(error, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> if (value == null) {
|
||||
this
|
||||
} else {
|
||||
Err(error())
|
||||
}
|
||||
|
||||
is Err -> Err(error())
|
||||
return when {
|
||||
isOk && value == null -> this
|
||||
else -> Err(error())
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Invokes an [action] if this [Result] is [Ok].
|
||||
* Invokes an [action] if this result [is ok][Result.isOk].
|
||||
*
|
||||
* - Rust: [Result.inspect](https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect)
|
||||
*/
|
||||
@ -13,7 +13,7 @@ public inline infix fun <V, E> Result<V, E>.onSuccess(action: (V) -> Unit): Resu
|
||||
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
if (this is Ok) {
|
||||
if (isOk) {
|
||||
action(value)
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ public inline infix fun <V, E> Result<V, E>.onSuccess(action: (V) -> Unit): Resu
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes an [action] if this [Result] is [Err].
|
||||
* Invokes an [action] if this result [is an error][Result.isErr].
|
||||
*
|
||||
* - Rust [Result.inspect_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err)
|
||||
*/
|
||||
@ -30,7 +30,7 @@ public inline infix fun <V, E> Result<V, E>.onFailure(action: (E) -> Unit): Resu
|
||||
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
if (this is Err) {
|
||||
if (isErr) {
|
||||
action(error)
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,14 @@ import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Returns [result] if this [Result] is [Err], otherwise this [Ok].
|
||||
* Returns [result] if this result [is an error][Result.isErr], otherwise [this].
|
||||
*
|
||||
* - Rust: [Result.or](https://doc.rust-lang.org/std/result/enum.Result.html#method.or)
|
||||
*/
|
||||
public infix fun <V, E, F> Result<V, E>.or(result: Result<V, F>): Result<V, F> {
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> result
|
||||
return when {
|
||||
isOk -> this.asOk()
|
||||
else -> result
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,8 +25,8 @@ public inline infix fun <V, E, F> Result<V, E>.or(result: () -> Result<V, F>): R
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err],
|
||||
* otherwise this [Ok].
|
||||
* Returns the [transformation][transform] of the [error][Result.error] if this result
|
||||
* [is an error][Result.isErr], otherwise [this].
|
||||
*
|
||||
* - Rust: [Result.or_else](https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else)
|
||||
*/
|
||||
@ -35,25 +35,26 @@ public inline infix fun <V, E, F> Result<V, E>.orElse(transform: (E) -> Result<V
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> transform(error)
|
||||
return when {
|
||||
isOk -> this.asOk()
|
||||
else -> transform(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws the [error][Err.error] if this [Result] is [Err], otherwise returns this [Ok].
|
||||
* Throws the [error][Result.error] if this result [is an error][Result.isErr], otherwise returns
|
||||
* [this].
|
||||
*/
|
||||
public fun <V, E : Throwable> Result<V, E>.orElseThrow(): Ok<V> {
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> throw error
|
||||
public fun <V, E : Throwable> Result<V, E>.orElseThrow(): Result<V, Nothing> {
|
||||
return when {
|
||||
isOk -> this.asOk()
|
||||
else -> throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws the [error][Err.error] if this [Result] is an [Err] and satisfies the given
|
||||
* [predicate], otherwise returns this [Result].
|
||||
* Throws the [error][Result.error] if this result [is an error][Result.isErr] and satisfies the
|
||||
* given [predicate], otherwise returns [this].
|
||||
*
|
||||
* @see [takeIf]
|
||||
*/
|
||||
@ -63,14 +64,14 @@ public inline fun <V, E : Throwable> Result<V, E>.throwIf(predicate: (E) -> Bool
|
||||
}
|
||||
|
||||
return when {
|
||||
this is Err && predicate(error) -> throw error
|
||||
isErr && predicate(error) -> throw error
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws the [error][Err.error] if this [Result] is an [Err] and _does not_ satisfy the
|
||||
* given [predicate], otherwise returns this [Result].
|
||||
* Throws the [error][Result.error] if this result [is an error][Result.isErr] and _does not_
|
||||
* satisfy the given [predicate], otherwise returns [this].
|
||||
*
|
||||
* @see [takeUnless]
|
||||
*/
|
||||
@ -79,12 +80,8 @@ public inline fun <V, E : Throwable> Result<V, E>.throwUnless(predicate: (E) ->
|
||||
callsInPlace(predicate, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> if (!predicate(error)) {
|
||||
throw error
|
||||
} else {
|
||||
this
|
||||
}
|
||||
return when {
|
||||
isErr && !predicate(error) -> throw error
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
@ -4,54 +4,58 @@ import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err],
|
||||
* otherwise this [Ok].
|
||||
* Returns the [transformation][transform] of the [error][Result.error] if this result
|
||||
* [is an error][Result.isErr], otherwise [this].
|
||||
*/
|
||||
public inline infix fun <V, E> Result<V, E>.recover(transform: (E) -> V): Ok<V> {
|
||||
public inline infix fun <V, E> Result<V, E>.recover(transform: (E) -> V): Result<V, Nothing> {
|
||||
contract {
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> Ok(transform(error))
|
||||
return when {
|
||||
isOk -> this.asOk()
|
||||
else -> Ok(transform(error))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [error][Err.error], catching and encapsulating any
|
||||
* thrown exception as a failure if this [Result] is [Err], otherwise this [Ok].
|
||||
* Returns the [transformation][transform] of the [error][Result.error] if this result
|
||||
* [is an error][Result.isErr], catching and encapsulating any thrown exception as an [Err],
|
||||
* otherwise [this].
|
||||
*/
|
||||
public inline infix fun <V, E> Result<V, E>.recoverCatching(transform: (E) -> V): Result<V, Throwable> {
|
||||
contract {
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> runCatching { transform(error) }
|
||||
return when {
|
||||
isOk -> this.asOk()
|
||||
else -> runCatching { transform(error) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err]
|
||||
* and satisfies the given [predicate], otherwise this [Result].
|
||||
* Returns the [transformation][transform] of the [error][Result.error] if this result
|
||||
* [is an error][Result.isErr] and satisfies the given [predicate], otherwise [this].
|
||||
*/
|
||||
public inline fun <V, E> Result<V, E>.recoverIf(predicate: (E) -> Boolean, transform: (E) -> V): Result<V, E> {
|
||||
public inline fun <V, E> Result<V, E>.recoverIf(
|
||||
predicate: (E) -> Boolean,
|
||||
transform: (E) -> V,
|
||||
): Result<V, E> {
|
||||
contract {
|
||||
callsInPlace(predicate, InvocationKind.AT_MOST_ONCE)
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when {
|
||||
this is Err && predicate(error) -> Ok(transform(error))
|
||||
isErr && predicate(error) -> Ok(transform(error))
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err]
|
||||
* and _does not_ satisfy the given [predicate], otherwise this [Result].
|
||||
* Returns the [transformation][transform] of the [error][Result.error] if this result
|
||||
* [is an error][Result.isErr] and _does not_ satisfy the given [predicate], otherwise [this].
|
||||
*/
|
||||
public inline fun <V, E> Result<V, E>.recoverUnless(predicate: (E) -> Boolean, transform: (E) -> V): Result<V, E> {
|
||||
contract {
|
||||
@ -60,29 +64,29 @@ public inline fun <V, E> Result<V, E>.recoverUnless(predicate: (E) -> Boolean, t
|
||||
}
|
||||
|
||||
return when {
|
||||
this is Err && !predicate(error) -> Ok(transform(error))
|
||||
isErr && !predicate(error) -> Ok(transform(error))
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err],
|
||||
* otherwise this [Result].
|
||||
* Returns the [transformation][transform] of the [error][Result.error] if this result
|
||||
* [is an error][Result.isErr], otherwise [this].
|
||||
*/
|
||||
public inline fun <V, E> Result<V, E>.andThenRecover(transform: (E) -> Result<V, E>): Result<V, E> {
|
||||
contract {
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> transform(error)
|
||||
return when {
|
||||
isOk -> this
|
||||
else -> transform(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err] and
|
||||
* satisfies the given [predicate], otherwise this [Result].
|
||||
* Returns the [transformation][transform] of the [error][Result.error] if this result
|
||||
* [is an error][Result.isErr] and satisfies the given [predicate], otherwise [this].
|
||||
*/
|
||||
public inline fun <V, E> Result<V, E>.andThenRecoverIf(
|
||||
predicate: (E) -> Boolean,
|
||||
@ -94,14 +98,14 @@ public inline fun <V, E> Result<V, E>.andThenRecoverIf(
|
||||
}
|
||||
|
||||
return when {
|
||||
this is Err && predicate(error) -> transform(error)
|
||||
isErr && predicate(error) -> transform(error)
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err]
|
||||
* and _does not_ satisfy the given [predicate], otherwise this [Result].
|
||||
* Returns the [transformation][transform] of the [error][Result.error] if this result
|
||||
* [is an error][Result.isErr] and _does not_ satisfy the given [predicate], otherwise [this].
|
||||
*/
|
||||
public inline fun <V, E> Result<V, E>.andThenRecoverUnless(
|
||||
predicate: (E) -> Boolean,
|
||||
@ -113,7 +117,7 @@ public inline fun <V, E> Result<V, E>.andThenRecoverUnless(
|
||||
}
|
||||
|
||||
return when {
|
||||
this is Err && !predicate(error) -> transform(error)
|
||||
isErr && !predicate(error) -> transform(error)
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,39 @@
|
||||
package com.github.michaelbull.result
|
||||
|
||||
/**
|
||||
* Returns a [Result] that [is ok][Result.isOk] and contains a [value][Result.value].
|
||||
*/
|
||||
@Suppress("FunctionName", "DEPRECATION")
|
||||
public fun <V> Ok(value: V): Result<V, Nothing> {
|
||||
return Ok(value, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Result] that [is an error][Result.isErr] and contains an [error][Result.error].
|
||||
*/
|
||||
@Suppress("FunctionName", "DEPRECATION")
|
||||
public fun <E> Err(error: E): Result<Nothing, E> {
|
||||
return Err(error, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafely casts this [Result<V, E>][Result] to [Result<U, Nothing>][Result], to be used inside
|
||||
* an explicit [isOk][Result.isOk] or [isErr][Result.isErr] guard.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
|
||||
public inline fun <V, E, U> Result<V, E>.asOk(): Result<U, Nothing> {
|
||||
return this as Result<U, Nothing>
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafely casts this [Result<V, E>][Result] to [Result<Nothing, F>][Result], to be used inside
|
||||
* an explicit [isOk][Result.isOk] or [isErr][Result.isErr] guard.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
|
||||
public inline fun <V, E, F> Result<V, E>.asErr(): Result<Nothing, F> {
|
||||
return this as Result<Nothing, F>
|
||||
}
|
||||
|
||||
/**
|
||||
* [Result] is a type that represents either success ([Ok]) or failure ([Err]).
|
||||
*
|
||||
@ -9,6 +43,12 @@ package com.github.michaelbull.result
|
||||
*/
|
||||
public sealed class Result<out V, out E> {
|
||||
|
||||
public abstract val value: V
|
||||
public abstract val error: E
|
||||
|
||||
public abstract val isOk: Boolean
|
||||
public abstract val isErr: Boolean
|
||||
|
||||
public abstract operator fun component1(): V?
|
||||
public abstract operator fun component2(): E?
|
||||
|
||||
@ -32,7 +72,22 @@ public sealed class Result<out V, out E> {
|
||||
/**
|
||||
* Represents a successful [Result], containing a [value].
|
||||
*/
|
||||
public class Ok<out V>(public val value: V) : Result<V, Nothing>() {
|
||||
@Deprecated(
|
||||
message = "Using Ok as a return type is deprecated.",
|
||||
replaceWith = ReplaceWith("Result<V, Nothing>"),
|
||||
)
|
||||
public class Ok<out V> internal constructor(
|
||||
override val value: V,
|
||||
@Suppress("UNUSED_PARAMETER") placeholder: Any?,
|
||||
) : Result<V, Nothing>() {
|
||||
|
||||
override val error: Nothing
|
||||
get() {
|
||||
throw NoSuchElementException()
|
||||
}
|
||||
|
||||
override val isOk: Boolean = true
|
||||
override val isErr: Boolean = false
|
||||
|
||||
override fun component1(): V = value
|
||||
override fun component2(): Nothing? = null
|
||||
@ -55,7 +110,22 @@ public class Ok<out V>(public val value: V) : Result<V, Nothing>() {
|
||||
/**
|
||||
* Represents a failed [Result], containing an [error].
|
||||
*/
|
||||
public class Err<out E>(public val error: E) : Result<Nothing, E>() {
|
||||
@Deprecated(
|
||||
message = "Using Err as a return type is deprecated.",
|
||||
replaceWith = ReplaceWith("Result<Nothing, E>"),
|
||||
)
|
||||
public class Err<out E> internal constructor(
|
||||
override val error: E,
|
||||
@Suppress("UNUSED_PARAMETER") placeholder: Any?,
|
||||
) : Result<Nothing, E>() {
|
||||
|
||||
override val value: Nothing
|
||||
get() {
|
||||
throw NoSuchElementException()
|
||||
}
|
||||
|
||||
override val isOk: Boolean = false
|
||||
override val isErr: Boolean = true
|
||||
|
||||
override fun component1(): Nothing? = null
|
||||
override fun component2(): E = error
|
||||
|
@ -1,8 +1,10 @@
|
||||
package com.github.michaelbull.result
|
||||
|
||||
/**
|
||||
* Returns an [Iterator] over the possibly contained [value][Ok.value].
|
||||
* The iterator yields one [value][Ok.value] if the [Result] is [Ok], otherwise throws [NoSuchElementException].
|
||||
* Returns an [Iterator] over the possibly contained [value][Result.value].
|
||||
*
|
||||
* The iterator yields one [value][Result.value] if this result [is ok][Result.isOk], otherwise
|
||||
* throws [NoSuchElementException].
|
||||
*
|
||||
* - Rust: [Result.iter](https://doc.rust-lang.org/std/result/enum.Result.html#method.iter)
|
||||
*/
|
||||
@ -11,8 +13,10 @@ public fun <V, E> Result<V, E>.iterator(): Iterator<V> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [MutableIterator] over the possibly contained [value][Ok.value].
|
||||
* The iterator yields one [value][Ok.value] if the [Result] is [Ok], otherwise throws [NoSuchElementException].
|
||||
* Returns a [MutableIterator] over the possibly contained [value][Result.value].
|
||||
*
|
||||
* The iterator yields one [value][Result.value] if this result [is ok][Result.isOk], otherwise
|
||||
* throws [NoSuchElementException].
|
||||
*
|
||||
* - Rust: [Result.iter_mut](https://doc.rust-lang.org/std/result/enum.Result.html#method.iter_mut)
|
||||
*/
|
||||
@ -23,31 +27,29 @@ public fun <V, E> Result<V, E>.mutableIterator(): MutableIterator<V> {
|
||||
private class ResultIterator<out V, out E>(private val result: Result<V, E>) : MutableIterator<V> {
|
||||
|
||||
/**
|
||||
* A flag indicating whether this [Iterator] has [yielded] its [Result].
|
||||
* A flag indicating whether this [Iterator] has [yielded] the [value][Result.value] of the
|
||||
* [result].
|
||||
*/
|
||||
private var yielded = false
|
||||
|
||||
/**
|
||||
* @return `true` if the [value][Ok.value] is not [yielded] and [Ok], `false` otherwise.
|
||||
* @return `true` if this [Iterator] has [yielded] the [value][Result.value] of the [result],
|
||||
* `false` otherwise.
|
||||
*/
|
||||
override fun hasNext(): Boolean {
|
||||
if (yielded) {
|
||||
return false
|
||||
}
|
||||
|
||||
return when (result) {
|
||||
is Ok -> true
|
||||
is Err -> false
|
||||
}
|
||||
return !yielded && result.isOk
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [Result's][Result] [value][Ok.value] if not [yielded] and [Ok].
|
||||
* @throws NoSuchElementException if the [Result] is [yielded] or is not [Ok].
|
||||
* Returns the [value][Result.value] of the [result] if not [yielded] and the result
|
||||
* [is ok][Result.isOk].
|
||||
*
|
||||
* @throws NoSuchElementException if already [yielded] or the result
|
||||
* [is an error][Result.isErr].
|
||||
*/
|
||||
override fun next(): V {
|
||||
if (!yielded && result is Ok) {
|
||||
yielded = true
|
||||
if (hasNext()) {
|
||||
remove()
|
||||
return result.value
|
||||
} else {
|
||||
throw NoSuchElementException()
|
||||
@ -55,7 +57,7 @@ private class ResultIterator<out V, out E>(private val result: Result<V, E>) : M
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags this [Iterator] as having [yielded] its [Result].
|
||||
* Flags this [Iterator] as having [yielded] the [value][Result.value] of the [result].
|
||||
*/
|
||||
override fun remove() {
|
||||
yielded = true
|
||||
|
@ -6,20 +6,21 @@ import kotlin.contracts.contract
|
||||
public class UnwrapException(message: String) : Exception(message)
|
||||
|
||||
/**
|
||||
* Unwraps a [Result], yielding the [value][Ok.value].
|
||||
* Returns the [value][Result.value] if this result [is ok][Result.isOk], otherwise throws an
|
||||
* [UnwrapException].
|
||||
*
|
||||
* - Rust: [Result.unwrap](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap)
|
||||
*
|
||||
* @throws UnwrapException if the [Result] is an [Err], with a message containing the [error][Err.error].
|
||||
* @throws UnwrapException if this result [is an error][Result.isErr].
|
||||
*/
|
||||
public fun <V, E> Result<V, E>.unwrap(): V {
|
||||
contract {
|
||||
returns() implies (this@unwrap is Ok<V>)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> throw UnwrapException("called Result.unwrap on an Err value $error")
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> throw UnwrapException("called Result.unwrap on an Err value $error")
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,12 +34,15 @@ public infix fun <V, E> Result<V, E>.expect(message: String): V {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a [Result], yielding the [value][Ok.value].
|
||||
* Returns the [value][Result.value] if this result [is ok][Result.isOk], otherwise throws an
|
||||
* [UnwrapException] with the specified [message].
|
||||
*
|
||||
* - Rust: [Result.expect](https://doc.rust-lang.org/std/result/enum.Result.html#method.expect)
|
||||
*
|
||||
* @param message The message to include in the [UnwrapException] if the [Result] is an [Err].
|
||||
* @throws UnwrapException if the [Result] is an [Err], with the specified [message].
|
||||
* @param message The message to include in the [UnwrapException] if this result
|
||||
* [is an error][Result.isErr].
|
||||
*
|
||||
* @throws UnwrapException if this result [is an error][Result.isErr].
|
||||
*/
|
||||
public inline infix fun <V, E> Result<V, E>.expect(message: () -> Any): V {
|
||||
contract {
|
||||
@ -46,27 +50,28 @@ public inline infix fun <V, E> Result<V, E>.expect(message: () -> Any): V {
|
||||
returns() implies (this@expect is Ok<V>)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> value
|
||||
is Err -> throw UnwrapException("${message()} $error")
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> throw UnwrapException("${message()} $error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a [Result], yielding the [error][Err.error].
|
||||
* Returns the [error][Result.error] if this result [is an error][Result.isErr], otherwise throws
|
||||
* an [UnwrapException].
|
||||
*
|
||||
* - Rust: [Result.unwrap_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err)
|
||||
*
|
||||
* @throws UnwrapException if the [Result] is [Ok], with a message containing the [value][Ok.value].
|
||||
* @throws UnwrapException if this result [is ok][Result.isOk].
|
||||
*/
|
||||
public fun <V, E> Result<V, E>.unwrapError(): E {
|
||||
contract {
|
||||
returns() implies (this@unwrapError is Err<E>)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> throw UnwrapException("called Result.unwrapError on an Ok value $value")
|
||||
is Err -> error
|
||||
return when {
|
||||
isErr -> error
|
||||
else -> throw UnwrapException("called Result.unwrapError on an Ok value $value")
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,12 +85,15 @@ public infix fun <V, E> Result<V, E>.expectError(message: String): E {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a [Result], yielding the [error][Err.error].
|
||||
* Returns the [error][Result.error] if this result [is an error][Result.isErr], otherwise throws
|
||||
* an [UnwrapException] with the specified [message].
|
||||
*
|
||||
* - Rust: [Result.expect_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.expect_err)
|
||||
*
|
||||
* @param message The message to include in the [UnwrapException] if the [Result] is [Ok].
|
||||
* @throws UnwrapException if the [Result] is [Ok], with the specified [message].
|
||||
* @param message The message to include in the [UnwrapException] if this result
|
||||
* [is ok][Result.isOk].
|
||||
*
|
||||
* @throws UnwrapException if this result [is ok][Result.isOk].
|
||||
*/
|
||||
public inline infix fun <V, E> Result<V, E>.expectError(message: () -> Any): E {
|
||||
contract {
|
||||
@ -93,8 +101,8 @@ public inline infix fun <V, E> Result<V, E>.expectError(message: () -> Any): E {
|
||||
returns() implies (this@expectError is Err<E>)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is Ok -> throw UnwrapException("${message()} $value")
|
||||
is Err -> error
|
||||
return when {
|
||||
isErr -> error
|
||||
else -> throw UnwrapException("${message()} $value")
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import kotlin.contracts.contract
|
||||
private typealias Producer<T, E> = () -> Result<T, E>
|
||||
|
||||
/**
|
||||
* Apply a [transformation][transform] to two [Results][Result], if both [Results][Result] are [Ok].
|
||||
* If not, the first argument which is an [Err] will propagate through.
|
||||
* Applies the given [transform] function to two [Results][Result], returning early with the first
|
||||
* [Err] if a transformation fails.
|
||||
*
|
||||
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map2
|
||||
*/
|
||||
@ -30,8 +30,8 @@ public inline fun <T1, T2, E, V> zip(
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a [transformation][transform] to three [Results][Result], if all [Results][Result] are [Ok].
|
||||
* If not, the first argument which is an [Err] will propagate through.
|
||||
* Applies the given [transform] function to three [Results][Result], returning early with the
|
||||
* first [Err] if a transformation fails.
|
||||
*
|
||||
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map3
|
||||
*/
|
||||
@ -58,8 +58,8 @@ public inline fun <T1, T2, T3, E, V> zip(
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a [transformation][transform] to four [Results][Result], if all [Results][Result] are [Ok].
|
||||
* If not, the first argument which is an [Err] will propagate through.
|
||||
* Applies the given [transform] function to four [Results][Result], returning early with the
|
||||
* first [Err] if a transformation fails.
|
||||
*
|
||||
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map4
|
||||
*/
|
||||
@ -90,8 +90,8 @@ public inline fun <T1, T2, T3, T4, E, V> zip(
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a [transformation][transform] to five [Results][Result], if all [Results][Result] are [Ok].
|
||||
* If not, the first argument which is an [Err] will propagate through.
|
||||
* Applies the given [transform] function to five [Results][Result], returning early with the
|
||||
* first [Err] if a transformation fails.
|
||||
*
|
||||
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map5
|
||||
*/
|
||||
@ -126,8 +126,8 @@ public inline fun <T1, T2, T3, T4, T5, E, V> zip(
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a [transformation][transform] to two [Results][Result], if both [Results][Result] are [Ok].
|
||||
* If not, the all arguments which are [Err] will be collected.
|
||||
* Applies the given [transform] function to two [Results][Result], collecting any result that
|
||||
* [is an error][Result.isErr] to a [List].
|
||||
*/
|
||||
public inline fun <T1, T2, E, V> zipOrAccumulate(
|
||||
producer1: () -> Result<T1, E>,
|
||||
@ -143,10 +143,12 @@ public inline fun <T1, T2, E, V> zipOrAccumulate(
|
||||
val result1 = producer1()
|
||||
val result2 = producer2()
|
||||
|
||||
return if (
|
||||
result1 is Ok &&
|
||||
result2 is Ok
|
||||
) {
|
||||
val results = listOf(
|
||||
producer1(),
|
||||
producer2(),
|
||||
)
|
||||
|
||||
return if (results.allOk()) {
|
||||
val transformed = transform(
|
||||
result1.value,
|
||||
result2.value,
|
||||
@ -154,18 +156,13 @@ public inline fun <T1, T2, E, V> zipOrAccumulate(
|
||||
|
||||
Ok(transformed)
|
||||
} else {
|
||||
val errors = listOf(
|
||||
result1,
|
||||
result2
|
||||
).mapNotNull { it.getError() }
|
||||
|
||||
Err(errors)
|
||||
Err(results.filterErrors())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a [transformation][transform] to three [Results][Result], if all [Results][Result] are [Ok].
|
||||
* If not, the all arguments which are [Err] will be collected.
|
||||
* Applies the given [transform] function to three [Results][Result], collecting any result that
|
||||
* [is an error][Result.isErr] to a [List].
|
||||
*/
|
||||
public inline fun <T1, T2, T3, E, V> zipOrAccumulate(
|
||||
producer1: () -> Result<T1, E>,
|
||||
@ -184,11 +181,13 @@ public inline fun <T1, T2, T3, E, V> zipOrAccumulate(
|
||||
val result2 = producer2()
|
||||
val result3 = producer3()
|
||||
|
||||
return if (
|
||||
result1 is Ok &&
|
||||
result2 is Ok &&
|
||||
result3 is Ok
|
||||
) {
|
||||
val results = listOf(
|
||||
result1,
|
||||
result2,
|
||||
result3,
|
||||
)
|
||||
|
||||
return if (results.allOk()) {
|
||||
val transformed = transform(
|
||||
result1.value,
|
||||
result2.value,
|
||||
@ -197,19 +196,13 @@ public inline fun <T1, T2, T3, E, V> zipOrAccumulate(
|
||||
|
||||
Ok(transformed)
|
||||
} else {
|
||||
val errors = listOf(
|
||||
result1,
|
||||
result2,
|
||||
result3
|
||||
).mapNotNull { it.getError() }
|
||||
|
||||
Err(errors)
|
||||
Err(results.filterErrors())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a [transformation][transform] to four [Results][Result], if all [Results][Result] are [Ok].
|
||||
* If not, the all arguments which are [Err] will be collected.
|
||||
* Applies the given [transform] function to four [Results][Result], collecting any result that
|
||||
* [is an error][Result.isErr] to a [List].
|
||||
*/
|
||||
public inline fun <T1, T2, T3, T4, E, V> zipOrAccumulate(
|
||||
producer1: () -> Result<T1, E>,
|
||||
@ -231,35 +224,30 @@ public inline fun <T1, T2, T3, T4, E, V> zipOrAccumulate(
|
||||
val result3 = producer3()
|
||||
val result4 = producer4()
|
||||
|
||||
return if (
|
||||
result1 is Ok &&
|
||||
result2 is Ok &&
|
||||
result3 is Ok &&
|
||||
result4 is Ok
|
||||
) {
|
||||
val results = listOf(
|
||||
result1,
|
||||
result2,
|
||||
result3,
|
||||
result4,
|
||||
)
|
||||
|
||||
return if (results.allOk()) {
|
||||
val transformed = transform(
|
||||
result1.value,
|
||||
result2.value,
|
||||
result3.value,
|
||||
result4.value
|
||||
result4.value,
|
||||
)
|
||||
|
||||
Ok(transformed)
|
||||
} else {
|
||||
val errors = listOf(
|
||||
result1,
|
||||
result2,
|
||||
result3,
|
||||
result4
|
||||
).mapNotNull { it.getError() }
|
||||
|
||||
Err(errors)
|
||||
Err(results.filterErrors())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a [transformation][transform] to five [Results][Result], if all [Results][Result] are [Ok].
|
||||
* If not, the all arguments which are [Err] will be collected.
|
||||
* Applies the given [transform] function to five [Results][Result], collecting any result that
|
||||
* [is an error][Result.isErr] to a [List].
|
||||
*/
|
||||
public inline fun <T1, T2, T3, T4, T5, E, V> zipOrAccumulate(
|
||||
producer1: () -> Result<T1, E>,
|
||||
@ -284,31 +272,25 @@ public inline fun <T1, T2, T3, T4, T5, E, V> zipOrAccumulate(
|
||||
val result4 = producer4()
|
||||
val result5 = producer5()
|
||||
|
||||
return if (
|
||||
result1 is Ok &&
|
||||
result2 is Ok &&
|
||||
result3 is Ok &&
|
||||
result4 is Ok &&
|
||||
result5 is Ok
|
||||
) {
|
||||
val results = listOf(
|
||||
result1,
|
||||
result2,
|
||||
result3,
|
||||
result4,
|
||||
result5
|
||||
)
|
||||
|
||||
return if (results.allOk()) {
|
||||
val transformed = transform(
|
||||
result1.value,
|
||||
result2.value,
|
||||
result3.value,
|
||||
result4.value,
|
||||
result5.value
|
||||
result5.value,
|
||||
)
|
||||
|
||||
Ok(transformed)
|
||||
} else {
|
||||
val errors = listOf(
|
||||
result1,
|
||||
result2,
|
||||
result3,
|
||||
result4,
|
||||
result5
|
||||
).mapNotNull { it.getError() }
|
||||
|
||||
Err(errors)
|
||||
Err(results.filterErrors())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user