Home > Blockchain >  val initialization using kotlin scope functions and elvis operator
val initialization using kotlin scope functions and elvis operator

Time:09-29

I want to initialize two vals depending on whether a third variable is null or not. This works:

class ABC(input: String?) {
    private val x: Int
    private val y: Int
    
    init {
        if (input != null) {
            x = 1
            y = 1
        } else {
            x = 2
            y = 2
        }
    }
}

But this doesn't compile:

class ABC(input: String?) {
    private val x: Int
    private val y: Int

    init {
        input?.also {
            x = 1
            y = 1
        } ?: also {
            x = 2
            y = 2
        }
    }
}

Why does the second example produce an error? Is it not logically the same as the first one? What is the most concise way to achieve the result?

CodePudding user response:

It logically evaluates the same to humans, but is too complex for the compiler. The compiler can handle a single if/else, but chaining nulls and the elvis operator is like two separate if-statements. Your second block of code is basically like the following, which the compiler will also complain about:

if (input != null) {
    x = 1
    y = 1
}
if (input == null) {
    x = 2
    y = 2
}

Chaining scope functions like this is error-prone anyway and should be avoided when possible. Your first block of code is far superior than the second for readability. When you're working with nullable properties or calling a series of functions in a builder-like manner, then chained scope functions may be a good choice. But in this case input is not a property so you can write more declarative (i.e. more readable) code without scope function chaining.

I think this is the most concise way to initialize your two variables as you have defined them:

class ABC(input: String?) {
    private val x: Int = if (input != null) 1 else 2
    private val y: Int = x
}
  • Related