https://kotlinlang.org logo
#arrow
Title
# arrow
j

Jorge Bo

03/13/2023, 10:49 PM
Hi, is it possible to do something like this on Arrow ?
Copy code
either {
    

   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()
  }
r

raulraja

03/14/2023, 7:24 AM
Hi @Jorge Bo, yes it is possible:
Copy code
enum 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-labels
s

simon.vergauwen

03/14/2023, 7:44 AM
Besides using
label
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
).
Copy code
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.
Copy code
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.
d

David

03/14/2023, 11:09 AM
Besides
ensure
, 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.html
s

simon.vergauwen

03/14/2023, 11:11 AM
Not entirely sure what you mean @David, but
ensure
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
.
d

David

03/14/2023, 11:15 AM
Yes, exactly. Just clarification that
shift
is the leave early function he was looking for, but agree
ensure
as you mentioned is the way to go here.
j

Jorge Bo

03/14/2023, 9:36 PM
thanks, both solutions suit my project
6 Views