Jorge Bo
03/13/2023, 10:49 PMeither {
val changeType: String
if (changeType == "do nothing") {
//leave early, this is not an error
return Either.Right("leave early)
}
..do some complicated logic and leave
"quit".right()
}
raulraja
03/14/2023, 7:24 AMenum class ChangeType {
DoNothing, RealChangeStartsHere
}
suspend fun foo(changeType: ChangeType): Either<Nothing, String> =
either myLabel@ {
if (changeType == ChangeType.DoNothing) {
return@myLabel "done"
}
"quit"
}
suspend fun main() {
println(foo(ChangeType.DoNothing)) // Either.Right(done)
println(foo(ChangeType.RealChangeStartsHere)) // Either.Right(quit)
}
Here myLabel
is a label for the either
block lambda which allows you to use it in a return
. This return can short-circuit up to the labeled boundary based on your logic.
This functionality it's not specific to Arrow but part of the Kotlin language. https://kotlinlang.org/docs/returns.html#return-to-labelssimon.vergauwen
03/14/2023, 7:44 AMlabel
you can also use some "functional tricks" to achieve this behavior.
You can wrap your Either.Left
in another Either
and flatten it with handleErrorWith
(or recover
on alpha
).
either<Either<E, String>, String> {
val changeType: String
ensure(changeType != "do nothing") { "leave early".right() }
..do some complicated logic and leave
"quit"
}.handleErrorWith { it } //recover { it.bind() }
Since you haven't shown any E
in your example it's also perfectly fine to do the following if you don't have any E
type in the left side.
val res: String = either<String, String> {
val changeType: String
ensure(changeType != "do nothing") { "leave early" }
..do some complicated logic and leave
"quit"
}.merge()
Either.Left
can also be used to short-circuit without being a failure but rather an "early exit" as you need here. We call it a logical failure to represent it means the computation stops, but it's not an "error" perse.David
03/14/2023, 11:09 AMensure
, which is more concise, shouldn’t shift
be an alternative in the EffectScope
?
https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core.continuations/-effect-scope/shift.htmlsimon.vergauwen
03/14/2023, 11:11 AMensure
is a DSL similar to kotlin.require
using if + shift
. So yes, you can use shift
as an alternative if you prefer to write explicit if
statements instead of ensure
.David
03/14/2023, 11:15 AMshift
is the leave early function he was looking for, but agree ensure
as you mentioned is the way to go here.Jorge Bo
03/14/2023, 9:36 PM