Kotlin 'let' плюс elvis, и случайные нулевые возвращаемые значения - PullRequest
0 голосов
/ 21 ноября 2018

Я был удивлен сегодня, узнав, что это восприятие явно идиоматического кода завершается неудачей:

class QuickTest {

    var nullableThing: Int? = 55

    var nullThing: Int? = null

    @Test
    fun `test let behaviour`() {
        nullableThing?.let {
            print("Nullable thing was non-null")
            nullThing?.apply { print("Never happens") }
        } ?: run {
            fail("This shouldn't have run")
        }
    }
}

Это происходит потому, что в сочетании с неявным возвратом nullThing?.apply{...} передает null в let, и, следовательно, в оператор elvisоценивает в ноль и запускает второй блок.

Это довольно ужасно обнаружить.Есть ли у нас подходящая альтернатива помимо обычной if/else без этой ловушки?

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Ваш случай является кандидатом на also тематический.Сравните два block действия:

fun <T> T.also(block: (T) -> Unit): T
fun <T, R> T.let(block: (T) -> R): R

nullableThing?.also {
    print("Nullable thing was non-null")
    nullThing?.apply { println("Never happens") }
} ?: run {
    fail("This shouldn't have run")
}

Другой идиоматический способ - использовать when выражение

when (nullableThing) {
    null ->
        print("Nullable thing was non-null")
        nullThing?.apply { println("Never happens") }
    else -> fail("This shouldn't have run")
}
0 голосов
/ 21 ноября 2018

Вы можете использовать also вместо let.also вернет nullableThing, тогда как let вернет все, что возвращает лямбда.

См. Эту статью: https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84 (пункт «3. Верните это и другие типы»).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...