Сравнивать foo?.let { bar(it) } ?: baz()
с if (foo != null) bar(foo) else baz()
.
опасно. Допустим, у вас есть функция: fun computeElements(): List<Int>? = emptyList()
Рассмотрите этот код:
val maxElement = computeElements()?.let { it.max() } ?: return
println("Max element was $maxElement")
По сравнениюto:
val list: List<Int>? = computeElements()
val maxElement = if (list != null) list.max() else return
println("Max element was $maxElement")
Вы можете подумать, что это две эквивалентные формы.Однако, если вы запустите оба, вы увидите, что первый ничего не печатает на стандартный вывод!
Это потому, что it.max()
возвращает null
для пустого списка (потому что нет элемента max),что приводит к оценке правой части выражения Элвиса, и поэтому функция return
s рано.
Короче говоря, ?.let { ... } ?: ...
разрешает обе ветви "if-else" подлежит оценке, что опасно.Помимо того, что эта форма не читается (if-else
понимается повсеместно, а let-run
нет), могут возникать незначительные ошибки.