parent
e81f581436
commit
27f0a63847
@ -12,18 +12,18 @@ private typealias Producer<T, E> = () -> Result<T, E>
|
|||||||
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map2
|
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map2
|
||||||
*/
|
*/
|
||||||
public inline fun <T1, T2, E, V> zip(
|
public inline fun <T1, T2, E, V> zip(
|
||||||
result1: Producer<T1, E>,
|
producer1: Producer<T1, E>,
|
||||||
result2: Producer<T2, E>,
|
producer2: Producer<T2, E>,
|
||||||
transform: (T1, T2) -> V
|
transform: (T1, T2) -> V
|
||||||
): Result<V, E> {
|
): Result<V, E> {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(result1, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(producer1, InvocationKind.EXACTLY_ONCE)
|
||||||
callsInPlace(result2, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer2, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result1().flatMap { v1 ->
|
return producer1().flatMap { v1 ->
|
||||||
result2().map { v2 ->
|
producer2().map { v2 ->
|
||||||
transform(v1, v2)
|
transform(v1, v2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,21 +36,21 @@ public inline fun <T1, T2, E, V> zip(
|
|||||||
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map3
|
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map3
|
||||||
*/
|
*/
|
||||||
public inline fun <T1, T2, T3, E, V> zip(
|
public inline fun <T1, T2, T3, E, V> zip(
|
||||||
result1: Producer<T1, E>,
|
producer1: Producer<T1, E>,
|
||||||
result2: Producer<T2, E>,
|
producer2: Producer<T2, E>,
|
||||||
result3: Producer<T3, E>,
|
producer3: Producer<T3, E>,
|
||||||
transform: (T1, T2, T3) -> V
|
transform: (T1, T2, T3) -> V
|
||||||
): Result<V, E> {
|
): Result<V, E> {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(result1, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(producer1, InvocationKind.EXACTLY_ONCE)
|
||||||
callsInPlace(result2, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer2, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(result3, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer3, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result1().flatMap { v1 ->
|
return producer1().flatMap { v1 ->
|
||||||
result2().flatMap { v2 ->
|
producer2().flatMap { v2 ->
|
||||||
result3().map { v3 ->
|
producer3().map { v3 ->
|
||||||
transform(v1, v2, v3)
|
transform(v1, v2, v3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,24 +64,24 @@ public inline fun <T1, T2, T3, E, V> zip(
|
|||||||
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map4
|
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map4
|
||||||
*/
|
*/
|
||||||
public inline fun <T1, T2, T3, T4, E, V> zip(
|
public inline fun <T1, T2, T3, T4, E, V> zip(
|
||||||
result1: Producer<T1, E>,
|
producer1: Producer<T1, E>,
|
||||||
result2: Producer<T2, E>,
|
producer2: Producer<T2, E>,
|
||||||
result3: Producer<T3, E>,
|
producer3: Producer<T3, E>,
|
||||||
result4: Producer<T4, E>,
|
producer4: Producer<T4, E>,
|
||||||
transform: (T1, T2, T3, T4) -> V
|
transform: (T1, T2, T3, T4) -> V
|
||||||
): Result<V, E> {
|
): Result<V, E> {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(result1, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(producer1, InvocationKind.EXACTLY_ONCE)
|
||||||
callsInPlace(result2, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer2, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(result3, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer3, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(result4, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer4, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result1().flatMap { v1 ->
|
return producer1().flatMap { v1 ->
|
||||||
result2().flatMap { v2 ->
|
producer2().flatMap { v2 ->
|
||||||
result3().flatMap { v3 ->
|
producer3().flatMap { v3 ->
|
||||||
result4().map { v4 ->
|
producer4().map { v4 ->
|
||||||
transform(v1, v2, v3, v4)
|
transform(v1, v2, v3, v4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,27 +96,27 @@ public inline fun <T1, T2, T3, T4, E, V> zip(
|
|||||||
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map5
|
* - Elm: http://package.elm-lang.org/packages/elm-lang/core/latest/Result#map5
|
||||||
*/
|
*/
|
||||||
public inline fun <T1, T2, T3, T4, T5, E, V> zip(
|
public inline fun <T1, T2, T3, T4, T5, E, V> zip(
|
||||||
result1: Producer<T1, E>,
|
producer1: Producer<T1, E>,
|
||||||
result2: Producer<T2, E>,
|
producer2: Producer<T2, E>,
|
||||||
result3: Producer<T3, E>,
|
producer3: Producer<T3, E>,
|
||||||
result4: Producer<T4, E>,
|
producer4: Producer<T4, E>,
|
||||||
result5: Producer<T5, E>,
|
producer5: Producer<T5, E>,
|
||||||
transform: (T1, T2, T3, T4, T5) -> V
|
transform: (T1, T2, T3, T4, T5) -> V
|
||||||
): Result<V, E> {
|
): Result<V, E> {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(result1, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(producer1, InvocationKind.EXACTLY_ONCE)
|
||||||
callsInPlace(result2, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer2, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(result3, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer3, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(result4, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer4, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(result5, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(producer5, InvocationKind.AT_MOST_ONCE)
|
||||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result1().flatMap { v1 ->
|
return producer1().flatMap { v1 ->
|
||||||
result2().flatMap { v2 ->
|
producer2().flatMap { v2 ->
|
||||||
result3().flatMap { v3 ->
|
producer3().flatMap { v3 ->
|
||||||
result4().flatMap { v4 ->
|
producer4().flatMap { v4 ->
|
||||||
result5().map { v5 ->
|
producer5().map { v5 ->
|
||||||
transform(v1, v2, v3, v4, v5)
|
transform(v1, v2, v3, v4, v5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,3 +124,191 @@ 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.
|
||||||
|
*/
|
||||||
|
public inline fun <T1, T2, E, V> zipOrAccumulate(
|
||||||
|
producer1: () -> Result<T1, E>,
|
||||||
|
producer2: () -> Result<T2, E>,
|
||||||
|
transform: (T1, T2) -> V,
|
||||||
|
): Result<V, List<E>> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(producer1, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer2, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val result1 = producer1()
|
||||||
|
val result2 = producer2()
|
||||||
|
|
||||||
|
return if (
|
||||||
|
result1 is Ok &&
|
||||||
|
result2 is Ok
|
||||||
|
) {
|
||||||
|
val transformed = transform(
|
||||||
|
result1.value,
|
||||||
|
result2.value,
|
||||||
|
)
|
||||||
|
|
||||||
|
Ok(transformed)
|
||||||
|
} else {
|
||||||
|
val errors = listOf(
|
||||||
|
result1,
|
||||||
|
result2
|
||||||
|
).mapNotNull { it.getError() }
|
||||||
|
|
||||||
|
Err(errors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public inline fun <T1, T2, T3, E, V> zipOrAccumulate(
|
||||||
|
producer1: () -> Result<T1, E>,
|
||||||
|
producer2: () -> Result<T2, E>,
|
||||||
|
producer3: () -> Result<T3, E>,
|
||||||
|
transform: (T1, T2, T3) -> V,
|
||||||
|
): Result<V, List<E>> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(producer1, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer2, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer3, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val result1 = producer1()
|
||||||
|
val result2 = producer2()
|
||||||
|
val result3 = producer3()
|
||||||
|
|
||||||
|
return if (
|
||||||
|
result1 is Ok &&
|
||||||
|
result2 is Ok &&
|
||||||
|
result3 is Ok
|
||||||
|
) {
|
||||||
|
val transformed = transform(
|
||||||
|
result1.value,
|
||||||
|
result2.value,
|
||||||
|
result3.value
|
||||||
|
)
|
||||||
|
|
||||||
|
Ok(transformed)
|
||||||
|
} else {
|
||||||
|
val errors = listOf(
|
||||||
|
result1,
|
||||||
|
result2,
|
||||||
|
result3
|
||||||
|
).mapNotNull { it.getError() }
|
||||||
|
|
||||||
|
Err(errors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public inline fun <T1, T2, T3, T4, E, V> zipOrAccumulate(
|
||||||
|
producer1: () -> Result<T1, E>,
|
||||||
|
producer2: () -> Result<T2, E>,
|
||||||
|
producer3: () -> Result<T3, E>,
|
||||||
|
producer4: () -> Result<T4, E>,
|
||||||
|
transform: (T1, T2, T3, T4) -> V,
|
||||||
|
): Result<V, Collection<E>> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(producer1, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer2, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer3, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer4, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val result1 = producer1()
|
||||||
|
val result2 = producer2()
|
||||||
|
val result3 = producer3()
|
||||||
|
val result4 = producer4()
|
||||||
|
|
||||||
|
return if (
|
||||||
|
result1 is Ok &&
|
||||||
|
result2 is Ok &&
|
||||||
|
result3 is Ok &&
|
||||||
|
result4 is Ok
|
||||||
|
) {
|
||||||
|
val transformed = transform(
|
||||||
|
result1.value,
|
||||||
|
result2.value,
|
||||||
|
result3.value,
|
||||||
|
result4.value
|
||||||
|
)
|
||||||
|
|
||||||
|
Ok(transformed)
|
||||||
|
} else {
|
||||||
|
val errors = listOf(
|
||||||
|
result1,
|
||||||
|
result2,
|
||||||
|
result3,
|
||||||
|
result4
|
||||||
|
).mapNotNull { it.getError() }
|
||||||
|
|
||||||
|
Err(errors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public inline fun <T1, T2, T3, T4, T5, E, V> zipOrAccumulate(
|
||||||
|
producer1: () -> Result<T1, E>,
|
||||||
|
producer2: () -> Result<T2, E>,
|
||||||
|
producer3: () -> Result<T3, E>,
|
||||||
|
producer4: () -> Result<T4, E>,
|
||||||
|
producer5: () -> Result<T5, E>,
|
||||||
|
transform: (T1, T2, T3, T4, T5) -> V,
|
||||||
|
): Result<V, Collection<E>> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(producer1, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer2, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer3, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer4, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(producer5, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val result1 = producer1()
|
||||||
|
val result2 = producer2()
|
||||||
|
val result3 = producer3()
|
||||||
|
val result4 = producer4()
|
||||||
|
val result5 = producer5()
|
||||||
|
|
||||||
|
return if (
|
||||||
|
result1 is Ok &&
|
||||||
|
result2 is Ok &&
|
||||||
|
result3 is Ok &&
|
||||||
|
result4 is Ok &&
|
||||||
|
result5 is Ok
|
||||||
|
) {
|
||||||
|
val transformed = transform(
|
||||||
|
result1.value,
|
||||||
|
result2.value,
|
||||||
|
result3.value,
|
||||||
|
result4.value,
|
||||||
|
result5.value
|
||||||
|
)
|
||||||
|
|
||||||
|
Ok(transformed)
|
||||||
|
} else {
|
||||||
|
val errors = listOf(
|
||||||
|
result1,
|
||||||
|
result2,
|
||||||
|
result3,
|
||||||
|
result4,
|
||||||
|
result5
|
||||||
|
).mapNotNull { it.getError() }
|
||||||
|
|
||||||
|
Err(errors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -199,4 +199,73 @@ class ZipTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ZipOrAccumulate {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedValueIfAllOk() {
|
||||||
|
val result = zipOrAccumulate(
|
||||||
|
{ Ok(10) },
|
||||||
|
{ Ok(20) },
|
||||||
|
{ Ok(30) },
|
||||||
|
{ Ok(40) },
|
||||||
|
{ Ok(50) },
|
||||||
|
) { a, b, c, d, e ->
|
||||||
|
a + b + c + d + e
|
||||||
|
}
|
||||||
|
|
||||||
|
result as Ok
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = 150,
|
||||||
|
actual = result.value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsAllErrsIfAllErr() {
|
||||||
|
val result = zipOrAccumulate(
|
||||||
|
{ Ok(10).and(Err("error one")) },
|
||||||
|
{ Ok(20).and(Err("error two")) },
|
||||||
|
{ Ok(30).and(Err("error three")) },
|
||||||
|
{ Ok(40).and(Err("error four")) },
|
||||||
|
{ Ok(50).and(Err("error five")) },
|
||||||
|
) { a, b, c, d, e ->
|
||||||
|
a + b + c + d + e
|
||||||
|
}
|
||||||
|
|
||||||
|
result as Err
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = listOf(
|
||||||
|
"error one",
|
||||||
|
"error two",
|
||||||
|
"error three",
|
||||||
|
"error four",
|
||||||
|
"error five",
|
||||||
|
),
|
||||||
|
actual = result.error,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsOneErrsIfOneOfErr() {
|
||||||
|
val result = zipOrAccumulate(
|
||||||
|
{ Ok(10) },
|
||||||
|
{ Ok(20).and(Err("only error")) },
|
||||||
|
{ Ok(30) },
|
||||||
|
{ Ok(40) },
|
||||||
|
{ Ok(50) },
|
||||||
|
) { a, b, c, d, e ->
|
||||||
|
a + b + c + d + e
|
||||||
|
}
|
||||||
|
|
||||||
|
result as Err
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = listOf("only error",),
|
||||||
|
actual = result.error,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user