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