kotlinidioms

What's the idiomatic way of assigning a nullable variable to 2 different blocks?


I thought the let and elvis operator would take care of nullable another way it seems to. In my above example, I want to check for a for being not null and returnSomethingNullable or in case a is null check for b and return a nullable as well. What would be the proper way of doing this?

fun foo(
    a: Int?,
    b: Int?,
    aCollection: List<FooBar>
): FooBar?{

    val result = a?.let{
        aCollection.firstOrNull{it.foo == a}//if this block returns null it goes in the ?: run case which is not what I want but returning null assigned to result
    }?: run{
        b?.let{
            aCollection.firstOrNull{it.bar == b}
        }
    }
     
    return result
}

Solution

  • Assuming the return value should be FooBar (and not Int, as your code suggests), I would recommend the following:

    val result = when {
        a != null -> aCollection.firstOrNull { it.foo == a }
        b != null -> aCollection.firstOrNull { it.bar == b }
        else -> null
    }
    

    If you do not want to duplicate aCollection.firstOrNull (maybe it is much more complex in your real scenario), you can use something like this:

    val result = when {
        a != null -> { it: FooBar -> it.foo == a }
        b != null -> { it: FooBar -> it.bar == b }
        else -> null
    }?.let(aCollection::firstOrNull)
    

    I would prefer the first one, though. It is better readable and easier to understand.