Rename Error class to Err

Avoids naming conflict with the stdlib's Error class, also now matches
Rust's naming.
This commit is contained in:
Michael Bull 2017-10-22 16:01:05 +01:00
parent 43128cf1cc
commit af13c9ee7c
19 changed files with 111 additions and 111 deletions

View File

@ -3,7 +3,7 @@
[![Release](https://jitpack.io/v/michaelbull/kotlin-result.svg)](https://jitpack.io/#michaelbull/kotlin-result) [![Build Status](https://travis-ci.org/michaelbull/kotlin-result.svg?branch=master)](https://travis-ci.org/michaelbull/kotlin-result) [![License](https://img.shields.io/github/license/michaelbull/kotlin-result.svg)](https://github.com/michaelbull/kotlin-result/blob/master/LICENSE) [![Release](https://jitpack.io/v/michaelbull/kotlin-result.svg)](https://jitpack.io/#michaelbull/kotlin-result) [![Build Status](https://travis-ci.org/michaelbull/kotlin-result.svg?branch=master)](https://travis-ci.org/michaelbull/kotlin-result) [![License](https://img.shields.io/github/license/michaelbull/kotlin-result.svg)](https://github.com/michaelbull/kotlin-result/blob/master/LICENSE)
[`Result<V, E>`][result] is a monad for modelling success ([`Ok`][result-ok]) or [`Result<V, E>`][result] is a monad for modelling success ([`Ok`][result-ok]) or
failure ([`Error`][result-error]) operations. failure ([`Err`][result-err]) operations.
## Inspiration ## Inspiration
@ -71,7 +71,7 @@ This project is available under the terms of the ISC license. See the
[result]: https://github.com/michaelbull/kotlin-result/blob/master/src/main/kotlin/com/github/michaelbull/result/Result.kt#L10 [result]: https://github.com/michaelbull/kotlin-result/blob/master/src/main/kotlin/com/github/michaelbull/result/Result.kt#L10
[result-ok]: https://github.com/michaelbull/kotlin-result/blob/master/src/main/kotlin/com/github/michaelbull/result/Result.kt#L27 [result-ok]: https://github.com/michaelbull/kotlin-result/blob/master/src/main/kotlin/com/github/michaelbull/result/Result.kt#L27
[result-error]: https://github.com/michaelbull/kotlin-result/blob/master/src/main/kotlin/com/github/michaelbull/result/Result.kt#L28 [result-err]: https://github.com/michaelbull/kotlin-result/blob/master/src/main/kotlin/com/github/michaelbull/result/Result.kt#L28
[unit-tests]: https://github.com/michaelbull/kotlin-result/tree/master/src/test/kotlin/com/github/michaelbull/result [unit-tests]: https://github.com/michaelbull/kotlin-result/tree/master/src/test/kotlin/com/github/michaelbull/result
[wiki]: https://github.com/michaelbull/kotlin-result/wiki [wiki]: https://github.com/michaelbull/kotlin-result/wiki
[wiki-elm]: https://github.com/michaelbull/kotlin-result/wiki/Elm [wiki-elm]: https://github.com/michaelbull/kotlin-result/wiki/Elm

View File

@ -1,5 +1,5 @@
group=com.github.michaelbull.kotlin-result group=com.github.michaelbull.kotlin-result
version=1.1.1-SNAPSHOT version=1.0.0-SNAPSHOT
dokkaVersion=0.9.15 dokkaVersion=0.9.15
gradleReleaseVersion=2.6.0 gradleReleaseVersion=2.6.0

View File

@ -4,12 +4,12 @@ package com.github.michaelbull.result
* - Rust: [Result.and](https://doc.rust-lang.org/std/result/enum.Result.html#method.and) * - Rust: [Result.and](https://doc.rust-lang.org/std/result/enum.Result.html#method.and)
* *
* @param result The [Result] to return if [Ok]. * @param result The [Result] to return if [Ok].
* @return The [result] if [Ok], otherwise [Error]. * @return The [result] if [Ok], otherwise [Err].
*/ */
infix fun <V, E> Result<V, E>.and(result: Result<V, E>): Result<V, E> { infix fun <V, E> Result<V, E>.and(result: Result<V, E>): Result<V, E> {
return when (this) { return when (this) {
is Ok -> result is Ok -> result
is Error -> this is Err -> this
} }
} }
@ -18,11 +18,11 @@ infix fun <V, E> Result<V, E>.and(result: Result<V, E>): Result<V, E> {
* - Rust: [Result.and_then](https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then) * - Rust: [Result.and_then](https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then)
* *
* @param transform The transformation to apply to the [value][Ok.value]. * @param transform The transformation to apply to the [value][Ok.value].
* @return The [transformed][transform] [Result] if [Ok], otherwise [Error]. * @return The [transformed][transform] [Result] if [Ok], otherwise [Err].
*/ */
infix inline fun <V, E, U> Result<V, E>.andThen(transform: (V) -> Result<U, E>): Result<U, E> { infix inline fun <V, E, U> Result<V, E>.andThen(transform: (V) -> Result<U, E>): Result<U, E> {
return when (this) { return when (this) {
is Ok -> transform(value) is Ok -> transform(value)
is Error -> this is Err -> this
} }
} }

View File

@ -9,19 +9,19 @@ package com.github.michaelbull.result
fun <V, E> Result<V, E>.get(): V? { fun <V, E> Result<V, E>.get(): V? {
return when (this) { return when (this) {
is Ok -> value is Ok -> value
is Error -> null is Err -> null
} }
} }
/** /**
* - Rust: [Result.err](https://doc.rust-lang.org/std/result/enum.Result.html#method.err) * - Rust: [Result.err](https://doc.rust-lang.org/std/result/enum.Result.html#method.err)
* *
* @return The [error][Error.error] if [Error], otherwise `null`. * @return The [error][Err.error] if [Err], otherwise `null`.
*/ */
fun <V, E> Result<V, E>.getError(): E? { fun <V, E> Result<V, E>.getError(): E? {
return when (this) { return when (this) {
is Ok -> null is Ok -> null
is Error -> error is Err -> error
} }
} }
@ -30,13 +30,13 @@ fun <V, E> Result<V, E>.getError(): E? {
* - Haskell: [Result.fromLeft](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:fromLeft) * - 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) * - Rust: [Result.unwrap_or](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or)
* *
* @param default The value to return if [Error]. * @param default The value to return if [Err].
* @return The [value][Ok.value] if [Ok], otherwise [default]. * @return The [value][Ok.value] if [Ok], otherwise [default].
*/ */
infix fun <V, E> Result<V, E>.getOr(default: V): V { infix fun <V, E> Result<V, E>.getOr(default: V): V {
return when (this) { return when (this) {
is Ok -> value is Ok -> value
is Error -> default is Err -> default
} }
} }
@ -44,12 +44,12 @@ infix fun <V, E> Result<V, E>.getOr(default: V): V {
* - Haskell: [Result.fromRight](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:fromRight) * - 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]. * @param default The error to return if [Ok].
* @return The [error][Error.error] if [Error], otherwise [default]. * @return The [error][Err.error] if [Err], otherwise [default].
*/ */
infix fun <V, E> Result<V, E>.getErrorOr(default: E): E { infix fun <V, E> Result<V, E>.getErrorOr(default: E): E {
return when (this) { return when (this) {
is Ok -> default is Ok -> default
is Error -> error is Err -> error
} }
} }
@ -57,12 +57,12 @@ infix fun <V, E> Result<V, E>.getErrorOr(default: E): E {
* - Elm: [Result.extract](http://package.elm-lang.org/packages/circuithub/elm-result-extra/1.4.0/Result-Extra#extract) * - Elm: [Result.extract](http://package.elm-lang.org/packages/circuithub/elm-result-extra/1.4.0/Result-Extra#extract)
* - Rust: [Result.unwrap_or_else](https://doc.rust-lang.org/src/core/result.rs.html#735-740) * - Rust: [Result.unwrap_or_else](https://doc.rust-lang.org/src/core/result.rs.html#735-740)
* *
* @param transform The transformation to apply to the [error][Error.error]. * @param transform The transformation to apply to the [error][Err.error].
* @return The [value][Ok.value] if [Ok], otherwise the [transformed][transform] [error][Error.error]. * @return The [value][Ok.value] if [Ok], otherwise the [transformed][transform] [error][Err.error].
*/ */
infix inline fun <V, E> Result<V, E>.getOrElse(transform: (E) -> V): V { infix inline fun <V, E> Result<V, E>.getOrElse(transform: (E) -> V): V {
return when (this) { return when (this) {
is Ok -> value is Ok -> value
is Error -> transform(error) is Err -> transform(error)
} }
} }

View File

@ -20,7 +20,7 @@ inline fun <T, R, E> Iterable<T>.fold(
is Ok -> { is Ok -> {
accumulator = operationResult.value accumulator = operationResult.value
} }
is Error -> return Error(operationResult.error) is Err -> return Err(operationResult.error)
} }
} }
@ -49,7 +49,7 @@ inline fun <T, R, E> List<T>.foldRight(
is Ok -> { is Ok -> {
accumulator = operationResult.value accumulator = operationResult.value
} }
is Error -> return Error(operationResult.error) is Err -> return Err(operationResult.error)
} }
} }
} }
@ -78,7 +78,7 @@ fun <V, E> Iterable<Result<V, E>>.combine(): Result<List<V>, E> {
return Ok(map { return Ok(map {
when (it) { when (it) {
is Ok -> it.value is Ok -> it.value
is Error -> return it is Err -> return it
} }
}) })
} }
@ -107,50 +107,50 @@ fun <V, E> Iterable<Result<V, E>>.getAll(): List<V> {
} }
/** /**
* Extracts from a vararg of [Results][Result] all the [Error] elements. All the [Error] elements * Extracts from a vararg of [Results][Result] all the [Err] elements. All the [Err] elements
* are extracted in order. * are extracted in order.
* *
* - Haskell: [Data.Either.rights](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:rights) * - Haskell: [Data.Either.rights](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:rights)
* *
* @param results The [Results][Result] from which to extract [Error] elements. * @param results The [Results][Result] from which to extract [Err] elements.
* @return The extracted [Error] elements. * @return The extracted [Err] elements.
*/ */
fun <V, E> getAllErrors(vararg results: Result<V, E>) = results.asIterable().getAllErrors() fun <V, E> getAllErrors(vararg results: Result<V, E>) = results.asIterable().getAllErrors()
/** /**
* Extracts from an [Iterable] of [Results][Result] all the [Error] elements. All the [Error] * Extracts from an [Iterable] of [Results][Result] all the [Err] elements. All the [Err]
* elements are extracted in order. * elements are extracted in order.
* *
* - Haskell: [Data.Either.rights](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:rights) * - Haskell: [Data.Either.rights](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:rights)
* *
* @return The extracted [Error] elements. * @return The extracted [Err] elements.
*/ */
fun <V, E> Iterable<Result<V, E>>.getAllErrors(): List<E> { fun <V, E> Iterable<Result<V, E>>.getAllErrors(): List<E> {
return filterIsInstance<Error<E>>().map { it.error } return filterIsInstance<Err<E>>().map { it.error }
} }
/** /**
* Partitions a vararg of [Results][Result] into a [Pair] of [Lists][List]. All the [Ok] elements * 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 [Error] elements are * are extracted, in order, to the [first][Pair.first] value. Similarly the [Err] elements are
* extracted to the [Pair.second] value. * extracted to the [Pair.second] value.
* *
* - Haskell: [Data.Either.partitionEithers](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:partitionEithers) * - Haskell: [Data.Either.partitionEithers](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:partitionEithers)
* *
* @param results The [Results][Result] to partition. * @param results The [Results][Result] to partition.
* @return A [Pair] of [Lists][List] where the [first][Pair.first] value * @return A [Pair] of [Lists][List] where the [first][Pair.first] value
* contains the [Ok] elements and the [second][Pair.second] value contains the [Error] elements. * contains the [Ok] elements and the [second][Pair.second] value contains the [Err] elements.
*/ */
fun <V, E> partition(vararg results: Result<V, E>) = results.asIterable().partition() fun <V, E> partition(vararg results: Result<V, E>) = results.asIterable().partition()
/** /**
* Partitions an [Iterable] of [Results][Result] into a [Pair] of [Lists][List]. All the [Ok] * 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 [Error] * elements are extracted, in order, to the [first][Pair.first] value. Similarly the [Err]
* elements are extracted to the [Pair.second] value. * elements are extracted to the [Pair.second] value.
* *
* - Haskell: [Data.Either.partitionEithers](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:partitionEithers) * - Haskell: [Data.Either.partitionEithers](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:partitionEithers)
* *
* @return A [Pair] of [Lists][List] where the [first][Pair.first] value * @return A [Pair] of [Lists][List] where the [first][Pair.first] value
* contains the [Ok] elements and the [second][Pair.second] value contains the [Error] elements. * contains the [Ok] elements and the [second][Pair.second] value contains the [Err] elements.
*/ */
fun <V, E> Iterable<Result<V, E>>.partition(): Pair<List<V>, List<E>> { fun <V, E> Iterable<Result<V, E>>.partition(): Pair<List<V>, List<E>> {
val values = mutableListOf<V>() val values = mutableListOf<V>()
@ -159,7 +159,7 @@ fun <V, E> Iterable<Result<V, E>>.partition(): Pair<List<V>, List<E>> {
forEach { result -> forEach { result ->
when (result) { when (result) {
is Ok -> values.add(result.value) is Ok -> values.add(result.value)
is Error -> errors.add(result.error) is Err -> errors.add(result.error)
} }
} }

View File

@ -2,50 +2,50 @@ package com.github.michaelbull.result
/** /**
* Maps a [Result<V, E>][Result] to [Result<U, E>][Result] by applying a function to a contained * Maps a [Result<V, E>][Result] to [Result<U, E>][Result] by applying a function to a contained
* [Ok] value, leaving an [Error] value untouched. * [Ok] value, leaving an [Err] value untouched.
* *
* - Elm: [Result.map](http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map) * - 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) * - 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) * - Rust: [Result.map](https://doc.rust-lang.org/std/result/enum.Result.html#method.map)
* *
* @param transform The transformation to apply to the [value][Ok.value] * @param transform The transformation to apply to the [value][Ok.value]
* @return The [transformed][transform] [Result] if [Ok], otherwise [Error]. * @return The [transformed][transform] [Result] if [Ok], otherwise [Err].
*/ */
infix inline fun <V, E, U> Result<V, E>.map(transform: (V) -> U): Result<U, E> { infix inline fun <V, E, U> Result<V, E>.map(transform: (V) -> U): Result<U, E> {
return when (this) { return when (this) {
is Ok -> Ok(transform(value)) is Ok -> Ok(transform(value))
is Error -> this is Err -> this
} }
} }
/** /**
* Maps a [Result<V, E>][Result] to [Result<V, F>][Result] by applying a function to a contained * Maps a [Result<V, E>][Result] to [Result<V, F>][Result] by applying a function to a contained
* [Error] value, leaving an [Ok] value untouched. * [Err] value, leaving an [Ok] value untouched.
* *
* - Elm: [Result.mapError](http://package.elm-lang.org/packages/elm-lang/core/latest/Result#mapError) * - 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) * - Haskell: [Data.Bifunctor.right](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifunctor.html#v:second)
* - Rust: [Result.map_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err) * - Rust: [Result.map_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err)
* *
* @param transform The transformation to apply to the [error][Error.error]. * @param transform The transformation to apply to the [error][Err.error].
* @return The [value][Ok.value] if [Ok], otherwise the [transformed][transform] [Error]. * @return The [value][Ok.value] if [Ok], otherwise the [transformed][transform] [Err].
*/ */
infix inline fun <V, E, F> Result<V, E>.mapError(transform: (E) -> F): Result<V, F> { infix inline fun <V, E, F> Result<V, E>.mapError(transform: (E) -> F): Result<V, F> {
return when (this) { return when (this) {
is Ok -> this is Ok -> this
is Error -> Error(transform(error)) is Err -> Err(transform(error))
} }
} }
/** /**
* Map a [Result<V, E>][Result] to `U` by applying either the [success] function if the [Result] * Map a [Result<V, E>][Result] to `U` by applying either the [success] function if the [Result]
* is [Ok] or the [failure] function if the [Result] is an [Error]. Both of these functions must * is [Ok] or the [failure] function if the [Result] is an [Err]. Both of these functions must
* return the same type (`U`). * return the same type (`U`).
* *
* - Elm: [Result.Extra.mapBoth](http://package.elm-lang.org/packages/circuithub/elm-result-extra/1.4.0/Result-Extra#mapBoth) * - Elm: [Result.Extra.mapBoth](http://package.elm-lang.org/packages/circuithub/elm-result-extra/1.4.0/Result-Extra#mapBoth)
* - Haskell: [Data.Either.either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:either) * - Haskell: [Data.Either.either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:either)
* *
* @param success The function to apply to `V` if [Ok]. * @param success The function to apply to `V` if [Ok].
* @param failure The function to apply to `E` if [Error]. * @param failure The function to apply to `E` if [Err].
* @return The mapped value. * @return The mapped value.
*/ */
inline fun <V, E, U> Result<V, E>.mapBoth( inline fun <V, E, U> Result<V, E>.mapBoth(
@ -54,19 +54,19 @@ inline fun <V, E, U> Result<V, E>.mapBoth(
): U { ): U {
return when (this) { return when (this) {
is Ok -> success(value) is Ok -> success(value)
is Error -> failure(error) is Err -> failure(error)
} }
} }
// TODO: better name? // TODO: better name?
/** /**
* Map a [Result<V, E>][Result] to [Result<U, F>][Result] by applying either the [success] function * Map a [Result<V, E>][Result] to [Result<U, F>][Result] by applying either the [success] function
* if the [Result] is [Ok] or the [failure] function if the [Result] is an [Error]. * if the [Result] is [Ok] or the [failure] function if the [Result] is an [Err].
* *
* - Haskell: [Data.Bifunctor.Bimap](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifunctor.html#v:bimap) * - Haskell: [Data.Bifunctor.Bimap](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifunctor.html#v:bimap)
* *
* @param success The function to apply to `V` if [Ok]. * @param success The function to apply to `V` if [Ok].
* @param failure The function to apply to `E` if [Error]. * @param failure The function to apply to `E` if [Err].
* @return The mapped [Result]. * @return The mapped [Result].
*/ */
inline fun <V, E, U, F> Result<V, E>.mapEither( inline fun <V, E, U, F> Result<V, E>.mapEither(
@ -75,6 +75,6 @@ inline fun <V, E, U, F> Result<V, E>.mapEither(
): Result<U, F> { ): Result<U, F> {
return when (this) { return when (this) {
is Ok -> Ok(success(value)) is Ok -> Ok(success(value))
is Error -> Error(failure(error)) is Err -> Err(failure(error))
} }
} }

View File

@ -7,7 +7,7 @@ package com.github.michaelbull.result
fun <V, E> Result<V, E>.onSuccess(callback: (V) -> Unit) = mapBoth(callback, {}) fun <V, E> Result<V, E>.onSuccess(callback: (V) -> Unit) = mapBoth(callback, {})
/** /**
* Calls a [callback] if the [Result] is [Error]. * Calls a [callback] if the [Result] is [Err].
* @param callback The function to call. * @param callback The function to call.
*/ */
fun <V, E> Result<V, E>.onFailure(callback: (E) -> Unit) = mapBoth({}, callback) fun <V, E> Result<V, E>.onFailure(callback: (E) -> Unit) = mapBoth({}, callback)

View File

@ -3,25 +3,25 @@ package com.github.michaelbull.result
/** /**
* - Rust: [Result.or](https://doc.rust-lang.org/std/result/enum.Result.html#method.or) * - Rust: [Result.or](https://doc.rust-lang.org/std/result/enum.Result.html#method.or)
* *
* @param result The [Result] to return if [Error]. * @param result The [Result] to return if [Err].
* @return The [result] if [Error], otherwise [Ok]. * @return The [result] if [Err], otherwise [Ok].
*/ */
infix fun <V, E> Result<V, E>.or(result: Result<V, E>): Result<V, E> { infix fun <V, E> Result<V, E>.or(result: Result<V, E>): Result<V, E> {
return when (this) { return when (this) {
is Ok -> this is Ok -> this
is Error -> result is Err -> result
} }
} }
/** /**
* - Rust: [Result.or_else](https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else) * - Rust: [Result.or_else](https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else)
* *
* @param transform The transformation to apply to the [error][Error.error]. * @param transform The transformation to apply to the [error][Err.error].
* @return The [transformed][transform] [Result] if [Error], otherwise [Ok]. * @return The [transformed][transform] [Result] if [Err], otherwise [Ok].
*/ */
infix inline fun <V, E> Result<V, E>.orElse(transform: (E) -> Result<V, E>): Result<V, E> { infix inline fun <V, E> Result<V, E>.orElse(transform: (E) -> Result<V, E>): Result<V, E> {
return when (this) { return when (this) {
is Ok -> this is Ok -> this
is Error -> transform(error) is Err -> transform(error)
} }
} }

View File

@ -1,7 +1,7 @@
package com.github.michaelbull.result package com.github.michaelbull.result
/** /**
* [Result] is a type that represents either success ([Ok]) or failure ([Error]). * [Result] is a type that represents either success ([Ok]) or failure ([Err]).
* *
* - Elm: [Result](http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Result) * - Elm: [Result](http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Result)
* - Haskell: [Data.Either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html) * - Haskell: [Data.Either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html)
@ -11,18 +11,18 @@ sealed class Result<out V, out E> {
companion object { companion object {
/** /**
* Invokes a [function] and wraps it in a [Result], returning an [Error] if a [Throwable] * Invokes a [function] and wraps it in a [Result], returning an [Err] if a [Throwable]
* was thrown, otherwise [Ok]. * was thrown, otherwise [Ok].
*/ */
inline fun <T> of(function: () -> T): Result<T, Throwable> { inline fun <T> of(function: () -> T): Result<T, Throwable> {
return try { return try {
Ok(function.invoke()) Ok(function.invoke())
} catch (t: Throwable) { } catch (t: Throwable) {
Error(t) Err(t)
} }
} }
} }
} }
data class Ok<out V> constructor(val value: V) : Result<V, Nothing>() data class Ok<out V> constructor(val value: V) : Result<V, Nothing>()
data class Error<out E> constructor(val error: E) : Result<Nothing, E>() data class Err<out E> constructor(val error: E) : Result<Nothing, E>()

View File

@ -41,7 +41,7 @@ private class ResultIterator<out V, out E>(private val result: Result<V, E>) : M
return when (result) { return when (result) {
is Ok -> true is Ok -> true
is Error -> false is Err -> false
} }
} }

View File

@ -7,12 +7,12 @@ class UnwrapException(message: String) : Exception(message)
* *
* - Rust: [Result.unwrap](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap) * - Rust: [Result.unwrap](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap)
* *
* @throws UnwrapException if the [Result] is an [Error], with a message containing the [error][Error.error]. * @throws UnwrapException if the [Result] is an [Err], with a message containing the [error][Err.error].
*/ */
fun <V, E> Result<V, E>.unwrap(): V { fun <V, E> Result<V, E>.unwrap(): V {
return when (this) { return when (this) {
is Ok -> value is Ok -> value
is Error -> throw UnwrapException("called Result.wrap on an Error value $error") is Err -> throw UnwrapException("called Result.wrap on an Err value $error")
} }
} }
@ -21,18 +21,18 @@ fun <V, E> Result<V, E>.unwrap(): V {
* *
* - Rust: [Result.expect](https://doc.rust-lang.org/std/result/enum.Result.html#method.expect) * - 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 [Error]. * @param message The message to include in the [UnwrapException] if the [Result] is an [Err].
* @throws UnwrapException if the [Result] is an [Error], with the specified [message]. * @throws UnwrapException if the [Result] is an [Err], with the specified [message].
*/ */
infix fun <V, E> Result<V, E>.expect(message: String): V { infix fun <V, E> Result<V, E>.expect(message: String): V {
return when (this) { return when (this) {
is Ok -> value is Ok -> value
is Error -> throw UnwrapException("$message $error") is Err -> throw UnwrapException("$message $error")
} }
} }
/** /**
* Unwraps a [Result], yielding the [error][Error.error]. * Unwraps a [Result], yielding the [error][Err.error].
* *
* - Rust: [Result.unwrap_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err) * - Rust: [Result.unwrap_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err)
* *
@ -41,12 +41,12 @@ infix fun <V, E> Result<V, E>.expect(message: String): V {
fun <V, E> Result<V, E>.unwrapError(): E { fun <V, E> Result<V, E>.unwrapError(): E {
return when (this) { return when (this) {
is Ok -> throw UnwrapException("called Result.unwrapError on an Ok value $value") is Ok -> throw UnwrapException("called Result.unwrapError on an Ok value $value")
is Error -> error is Err -> error
} }
} }
/** /**
* Unwraps a [Result], yielding the [error][Error.error]. * Unwraps a [Result], yielding the [error][Err.error].
* *
* - Rust: [Result.expect_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.expect_err) * - Rust: [Result.expect_err](https://doc.rust-lang.org/std/result/enum.Result.html#method.expect_err)
* *
@ -56,6 +56,6 @@ fun <V, E> Result<V, E>.unwrapError(): E {
infix fun <V, E> Result<V, E>.expectError(message: String): E { infix fun <V, E> Result<V, E>.expectError(message: String): E {
return when (this) { return when (this) {
is Ok -> throw UnwrapException("$message $value") is Ok -> throw UnwrapException("$message $value")
is Error -> error is Err -> error
} }
} }

View File

@ -16,7 +16,7 @@ internal class AndTest {
@Test @Test
internal fun `and should return the result value if not ok`() { internal fun `and should return the result value if not ok`() {
val error = Ok(300).and(Error("hello world")).getError() val error = Ok(300).and(Err("hello world")).getError()
assertThat(error, equalTo("hello world")) assertThat(error, equalTo("hello world"))
} }
@ -28,7 +28,7 @@ internal class AndTest {
@Test @Test
internal fun `andThen should return the result error if not ok`() { internal fun `andThen should return the result error if not ok`() {
val error = Ok(20).andThen { Ok(it + 43) }.andThen { Error(AndError) }.getError()!! val error = Ok(20).andThen { Ok(it + 43) }.andThen { Err(AndError) }.getError()!!
assertThat(error, sameInstance(AndError)) assertThat(error, sameInstance(AndError))
} }
} }

View File

@ -13,7 +13,7 @@ internal class GetTest {
@Test @Test
internal fun `get should return null if not ok`() { internal fun `get should return null if not ok`() {
val value = Error("error").get() val value = Err("error").get()
assertThat(value, equalTo(null)) assertThat(value, equalTo(null))
} }
@ -25,7 +25,7 @@ internal class GetTest {
@Test @Test
internal fun `getError should return the result error if not ok`() { internal fun `getError should return the result error if not ok`() {
val error = Error("example").getError() val error = Err("example").getError()
assertThat(error, equalTo("example")) assertThat(error, equalTo("example"))
} }
@ -37,7 +37,7 @@ internal class GetTest {
@Test @Test
internal fun `getOr should return default value if not ok`() { internal fun `getOr should return default value if not ok`() {
val value = Error("error").getOr("default") val value = Err("error").getOr("default")
assertThat(value, equalTo("default")) assertThat(value, equalTo("default"))
} }
@ -49,7 +49,7 @@ internal class GetTest {
@Test @Test
internal fun `getErrorOr should return the result error if not ok`() { internal fun `getErrorOr should return the result error if not ok`() {
val error = Error("hello").getErrorOr("world") val error = Err("hello").getErrorOr("world")
assertThat(error, equalTo("hello")) assertThat(error, equalTo("hello"))
} }
@ -61,7 +61,7 @@ internal class GetTest {
@Test @Test
internal fun `getOrElse should return the transformed result error if ok`() { internal fun `getOrElse should return the transformed result error if ok`() {
val value = Error("hello").getOrElse { "world" } val value = Err("hello").getOrElse { "world" }
assertThat(value, equalTo("world")) assertThat(value, equalTo("world"))
} }
} }

View File

@ -34,14 +34,14 @@ internal class IterableTest {
initial = 1, initial = 1,
operation = { a, b -> operation = { a, b ->
when (b) { when (b) {
(5 + 10) -> Error(IterableError.IterableError1) (5 + 10) -> Err(IterableError.IterableError1)
(5 + 10 + 15 + 20) -> Error(IterableError.IterableError2) (5 + 10 + 15 + 20) -> Err(IterableError.IterableError2)
else -> Ok(a * b) else -> Ok(a * b)
} }
} }
) )
result as Error result as Err
val matcher: Matcher<IterableError> = sameInstance(IterableError.IterableError1) val matcher: Matcher<IterableError> = sameInstance(IterableError.IterableError1)
assertThat(result.error, matcher) assertThat(result.error, matcher)
@ -65,14 +65,14 @@ internal class IterableTest {
initial = 38500, initial = 38500,
operation = { a, b -> operation = { a, b ->
when (b) { when (b) {
(((38500 / 40) / 20) / 10) -> Error(IterableError.IterableError1) (((38500 / 40) / 20) / 10) -> Err(IterableError.IterableError1)
((38500 / 40) / 20) -> Error(IterableError.IterableError2) ((38500 / 40) / 20) -> Err(IterableError.IterableError2)
else -> Ok(b / a) else -> Ok(b / a)
} }
} }
) )
result as Error result as Err
assertThat(result.error, sameError(IterableError.IterableError2)) assertThat(result.error, sameError(IterableError.IterableError2))
} }
@ -96,13 +96,13 @@ internal class IterableTest {
val result = combine( val result = combine(
Ok(20), Ok(20),
Ok(40), Ok(40),
Error(IterableError.IterableError1), Err(IterableError.IterableError1),
Ok(60), Ok(60),
Error(IterableError.IterableError2), Err(IterableError.IterableError2),
Ok(80) Ok(80)
) )
result as Error result as Err
assertThat(result.error, sameError(IterableError.IterableError1)) assertThat(result.error, sameError(IterableError.IterableError1))
} }
@ -112,9 +112,9 @@ internal class IterableTest {
val values = getAll( val values = getAll(
Ok("hello"), Ok("hello"),
Ok("big"), Ok("big"),
Error(IterableError.IterableError2), Err(IterableError.IterableError2),
Ok("wide"), Ok("wide"),
Error(IterableError.IterableError1), Err(IterableError.IterableError1),
Ok("world") Ok("world")
) )
@ -128,15 +128,15 @@ internal class IterableTest {
@Test @Test
internal fun `getAllErrors should return all of the result errors`() { internal fun `getAllErrors should return all of the result errors`() {
val errors = getAllErrors( val errors = getAllErrors(
Error(IterableError.IterableError2), Err(IterableError.IterableError2),
Ok("haskell"), Ok("haskell"),
Error(IterableError.IterableError2), Err(IterableError.IterableError2),
Ok("f#"), Ok("f#"),
Error(IterableError.IterableError1), Err(IterableError.IterableError1),
Ok("elm"), Ok("elm"),
Error(IterableError.IterableError1), Err(IterableError.IterableError1),
Ok("clojure"), Ok("clojure"),
Error(IterableError.IterableError2) Err(IterableError.IterableError2)
) )
assertThat(errors.size, equalTo(5)) assertThat(errors.size, equalTo(5))
@ -150,15 +150,15 @@ internal class IterableTest {
@Test @Test
internal fun `partition should return a pair of all the result values and errors`() { internal fun `partition should return a pair of all the result values and errors`() {
val pairs = partition( val pairs = partition(
Error(IterableError.IterableError2), Err(IterableError.IterableError2),
Ok("haskell"), Ok("haskell"),
Error(IterableError.IterableError2), Err(IterableError.IterableError2),
Ok("f#"), Ok("f#"),
Error(IterableError.IterableError1), Err(IterableError.IterableError1),
Ok("elm"), Ok("elm"),
Error(IterableError.IterableError1), Err(IterableError.IterableError1),
Ok("clojure"), Ok("clojure"),
Error(IterableError.IterableError2) Err(IterableError.IterableError2)
) )
val values = pairs.first val values = pairs.first

View File

@ -27,9 +27,9 @@ internal class MapTest {
@Test @Test
internal fun `map should return the result error if not ok`() { internal fun `map should return the result error if not ok`() {
val result = Error(MapError.HelloError).map { "hello $it" } val result = Err(MapError.HelloError).map { "hello $it" }
result as Error result as Err
assertThat(result.error, sameError(MapError.HelloError)) assertThat(result.error, sameError(MapError.HelloError))
} }
@ -46,13 +46,13 @@ internal class MapTest {
.map { "$it me" } .map { "$it me" }
.andThen { .andThen {
when (it) { when (it) {
"let me" -> Error(MapError.CustomError("$it $it")) "let me" -> Err(MapError.CustomError("$it $it"))
else -> Ok("$it get") else -> Ok("$it get")
} }
} }
.mapError { MapError.CustomError("${it.reason} get what i want") } .mapError { MapError.CustomError("${it.reason} get what i want") }
result as Error result as Err
assertThat(result.error.reason, equalTo("let me let me get what i want")) assertThat(result.error.reason, equalTo("let me let me get what i want"))
} }
@ -69,7 +69,7 @@ internal class MapTest {
@Test @Test
internal fun `mapBoth should return the transformed result error if not ok`() { internal fun `mapBoth should return the transformed result error if not ok`() {
val error = Error(MapError.CustomError("this")).mapBoth( val error = Err(MapError.CustomError("this")).mapBoth(
success = { "$it charming" }, success = { "$it charming" },
failure = { "${it.reason} man" } failure = { "${it.reason} man" }
) )
@ -91,12 +91,12 @@ internal class MapTest {
@Test @Test
internal fun `mapEither should return the transformed result error if not ok`() { internal fun `mapEither should return the transformed result error if not ok`() {
val result = Error("the reckless").mapEither( val result = Err("the reckless").mapEither(
success = { "the wild youth" }, success = { "the wild youth" },
failure = { MapError.CustomError("the truth") } failure = { MapError.CustomError("the truth") }
) )
result as Error result as Err
assertThat(result.error.reason, equalTo("the truth")) assertThat(result.error.reason, equalTo("the truth"))
} }

View File

@ -18,14 +18,14 @@ internal class OnTest {
@Test @Test
internal fun `onSuccess should not invoke the callback when result is not ok`() { internal fun `onSuccess should not invoke the callback when result is not ok`() {
val counter = Counter(200) val counter = Counter(200)
Error(CounterError).onSuccess { counter.count -= 50 } Err(CounterError).onSuccess { counter.count -= 50 }
assertThat(counter.count, equalTo(200)) assertThat(counter.count, equalTo(200))
} }
@Test @Test
internal fun `onFailure should invoke the callback when result is not ok`() { internal fun `onFailure should invoke the callback when result is not ok`() {
val counter = Counter(555) val counter = Counter(555)
Error(CounterError).onFailure { counter.count += 100 } Err(CounterError).onFailure { counter.count += 100 }
assertThat(counter.count, equalTo(655)) assertThat(counter.count, equalTo(655))
} }

View File

@ -15,7 +15,7 @@ internal class OrTest {
@Test @Test
internal fun `or should return the default value if not ok`() { internal fun `or should return the default value if not ok`() {
val value = Error(OrError).or(Ok(5000)).get() val value = Err(OrError).or(Ok(5000)).get()
assertThat(value, equalTo(5000)) assertThat(value, equalTo(5000))
} }
@ -27,7 +27,7 @@ internal class OrTest {
@Test @Test
internal fun `orElse should return the transformed value if not ok`() { internal fun `orElse should return the transformed value if not ok`() {
val value = Error(4000).orElse { Ok(2000) }.get() val value = Err(4000).orElse { Ok(2000) }.get()
assertThat(value, equalTo(2000)) assertThat(value, equalTo(2000))
} }
} }

View File

@ -14,7 +14,7 @@ internal class ResultIteratorTest {
@Test @Test
internal fun `hasNext should return false if result is not ok`() { internal fun `hasNext should return false if result is not ok`() {
val iterator = Error("hello").iterator() val iterator = Err("hello").iterator()
assertThat(iterator.hasNext(), equalTo(false)) assertThat(iterator.hasNext(), equalTo(false))
} }
@ -33,7 +33,7 @@ internal class ResultIteratorTest {
@Test @Test
internal fun `next should throw NoSuchElementException if unyielded and result is not ok`() { internal fun `next should throw NoSuchElementException if unyielded and result is not ok`() {
val iterator = Error("hello").iterator() val iterator = Err("hello").iterator()
assertThrows(NoSuchElementException::class.java) { assertThrows(NoSuchElementException::class.java) {
iterator.next() iterator.next()

View File

@ -15,10 +15,10 @@ internal class UnwrapTest {
@Test @Test
internal fun `unwrap should throw an UnwrapException if not ok`() { internal fun `unwrap should throw an UnwrapException if not ok`() {
val throwable = assertThrows(UnwrapException::class.java, { val throwable = assertThrows(UnwrapException::class.java, {
Error(5000).unwrap() Err(5000).unwrap()
}) })
assertThat(throwable.message, equalTo("called Result.wrap on an Error value 5000")) assertThat(throwable.message, equalTo("called Result.wrap on an Err value 5000"))
} }
@Test @Test
@ -30,7 +30,7 @@ internal class UnwrapTest {
@Test @Test
internal fun `expect should throw an UnwrapException with a specified message if not ok`() { internal fun `expect should throw an UnwrapException with a specified message if not ok`() {
val throwable = assertThrows(UnwrapException::class.java, { val throwable = assertThrows(UnwrapException::class.java, {
Error(1994).expect("the year should be") Err(1994).expect("the year should be")
}) })
assertThat(throwable.message, equalTo("the year should be 1994")) assertThat(throwable.message, equalTo("the year should be 1994"))
@ -47,7 +47,7 @@ internal class UnwrapTest {
@Test @Test
internal fun `unwrapError should return the result error if not ok`() { internal fun `unwrapError should return the result error if not ok`() {
val error = Error("example").unwrapError() val error = Err("example").unwrapError()
assertThat(error, equalTo("example")) assertThat(error, equalTo("example"))
} }
@ -62,7 +62,7 @@ internal class UnwrapTest {
@Test @Test
internal fun `expectError should return the result error if not ok`() { internal fun `expectError should return the result error if not ok`() {
val error = Error(2010).expectError("the year should be") val error = Err(2010).expectError("the year should be")
assertThat(error, equalTo(2010)) assertThat(error, equalTo(2010))
} }
} }