Jeff
05/12/2021, 6:58 PMsourceA().handleErrorWith {
sourceB().handleErrorWith {
sourceC()
}
}
Joram Visser
05/12/2021, 7:10 PMsourceA()
.flatMap { sourceB() }
.flatMap { sourceC() }
If you only want to invoke sourceB and sourceC in cases errors occurred, then I guess your approach is fine.Jeff
05/12/2021, 8:05 PMJoram Visser
05/12/2021, 8:30 PMJoram Visser
05/12/2021, 8:32 PMJeff
05/13/2021, 3:12 AMfirstRight(a(), b(), c()).fold(onA, onB, onC)
Which wouldn’t cancel on a Left but would cancel on a Right and would return that Right.Joram Visser
05/13/2021, 6:44 AMsimon.vergauwen
05/13/2021, 8:20 AMswap
on Either
which swaps the side so you could do.
race({ eitherA().swap() }, { eitherB().swap() }).swap()
It's a bit tedious but for sure the easiest way to achieve your tasks without to much overhead since 3x swap is minimal compared to dispatching 3 times. (2 for launching tasks, and one again to return to original ctx).simon.vergauwen
05/13/2021, 8:21 AMhandleErrorWith
is the correct way of chaining Left
you can consider it flatMapLeft
and thus you could also write a eitherLeft { }
block for it if you'd want to.Joram Visser
05/13/2021, 8:37 AMsimon.vergauwen
05/13/2021, 8:41 AMJoram Visser
05/13/2021, 8:46 AMkeepRetryingSourceAUntilItYieldsARight(maxRetries)
Joram Visser
05/13/2021, 8:47 AMJoram Visser
05/13/2021, 8:48 AMsimon.vergauwen
05/13/2021, 8:55 AMLeft
.
This is a snippet I whipped together and should be thoroughly tested but basically, it just keeps track of how many task have finished and the first Left
it encounters.
If all task run out without a Right
winning the race than the first encountered Left
will be returned rather than the last which marked the race as finsihed with all Left
.
The first Right
wins the race.
This is achieved by making Left
suspend and thus not allowing them to complete the race
suspend fun <E, A> firstRight(fa: suspend () -> Either<E, A>, fb: suspend () -> Either<E, A>): Either<E, A> {
var firstLeft: Atomic<Either<E, A>?> = Atomic(null)
var finished: Atomic = Atomic(0)
suspend fun Either<E, A>.suspendOnLeft(): Either<E, A> =
when(this) {
is Right -> this
is Left -> when {
finished.get() == 2 -> firstLeft.get()!!
else -> {
firstLeft.update { current -> if(current == null) this else current }
finished.update(Int:inc)
suspendCoroutine<A> { }
}
}
return race({ fa().suspendOnLeft() }, { fb().suspendOnLeft() }) }
}
simon.vergauwen
05/13/2021, 8:56 AMif(firstLeft.get() != null) finished.update(Int::inc) else firstLeft.update { this }
This line needs to be rewritten to use modify
on Atomic
instead since this is not atomically soundsimon.vergauwen
05/13/2021, 9:02 AMsimon.vergauwen
05/13/2021, 9:04 AMsuspend
and Either
is an important focus of Arrow