```private fun parseArgument( maybeArgument: C...
# getting-started
m
Copy code
private fun parseArgument(
    maybeArgument: ConeKotlinType,
    session: FirSession,
): Either<ClassId, ClassKind?> {
    val id = maybeArgument.classId ?: return Either.Bar(null)
    val kind = session.classFromId(id)?.classKind ?: return Either.Bar(null)
    return when {
        kind.isAnnotationClass -> Either.Foo(id)
        else -> Either.Bar(kind)
    }
}
How can I consolidate the duplicate
return Either.Bar(null)
statements?
y
You could have
val default = Either.Bar(null)
and simply return that Of course, there's a nice #C5UPMM0A0 solution here if you want it:
Copy code
// Arrow's Either type has its type parameters the other way around
// You don't have to use Arrow's Either, you can make Raise work with your own type, I'm just using it for brevity
private fun parseArgument(
    maybeArgument: ConeKotlinType,
    session: FirSession,
): Either<ClassKind?, ClassId> = either {
    singleton({ raise(null) }) { // singleton gives access to the `.bind()` syntax for nullables
        val id = maybeArgument.classId.bind()
        val kind = session.classFromId(id)?.classKind.bind()
        ensure(<http://kind.is|kind.is>AnnotationClass) { id }
        kind
    }
}
m
1. Change from
Either
to a sealed hierarchy. Your
Either
is not a bi-state, it's a tri-state
Id | Kind | Null
. Then you'll get
return InvalidArgument
and writing it twice is fine. 2. Actually, writing something twice is totally fine even for the current form. 3. You can delay making the decision to the very last moment.
Copy code
private fun parseArgument(
    maybeArgument: ConeKotlinType,
    session: FirSession,
): Either<ClassId, ClassKind?> {
    val id: ClassId? = maybeArgument.classId
    val kind: ClassKind? = id?.let { session.classFromId(it)?.classKind }
    return when {
        id == null | kind == null -> Either.Bar(null)
        kind.isAnnotationClass -> Either.Foo(id)
        else -> Either.Bar(kind)
    }
}
➕ 1
m
Change from
Either
to a sealed hierarchy. […] Then you'll get
return InvalidArgument
and writing it twice is fine.
@Marat Akhin I don’t understand what you mean by this.
y
Copy code
sealed interface AnnotationResult
data class AnnotationId(val id: ClassId): AnnotationResult
data class InvalidClassKind(val kind: ClassKind): AnnotationResult
data object InvalidArgument: AnnotationResult
This can work fine with
Either
though:
Copy code
sealed interface AnnotationError
data class InvalidClassKind(val kind: ClassKind): AnnotationError
data object InvalidArgument: AnnotationError
typealias AnnotationResult = Either<ClassId, AnnotationError>