https://kotlinlang.org logo
#russian
Title
# russian
a

Alexjok

04/02/2019, 10:31 AM
Привет всем! Есть код:
Copy code
fun main(args: Array<String>) {
    val intList = mutableListOf(1,2,5)
    test(intList)
}
fun test(objectIds: MutableList<Int>?) {
    when (objectIds.isNullOrEmpty()) {
        true ->{
            println("true")
        }

        false -> {
            val maxObjectId = objectIds.max()!!.let {
                objectIds.remove(it)
                return@let it.toLong()
            }
            println(maxObjectId)
        }
    }
}
В блоке when метода test() происходит проверка на null и по идее когда мы попадаем в false нам известно: 1) лист не пустой 2) метод max() должен, что-то вернуть. Но IDE настойчиво требует поставить !!, почему так происходит и есть ли способ избавиться от восклицательных знаков?
g

gildor

04/02/2019, 10:37 AM
на null проверка работает, но она не работает для max()
потому что нет такого контракта как “коллекция не пустая”
к тому же в данном случае это было бы не безопасно в любом случае, ведь компайлер не знаете, что никто этот MutableList не изменил из вне, из другого потока
хотя контракт для “коллекция не пустая” был бы в каких то случаях полезен, но не очень понятно как его имплементить, контракт же ничего не знает о том как коллекция заимплеменчена, поэтому метод max() сделать безапасным никак не получится
можно этот код переписать что бы без всяких доп ухищрений с контрактами и !! работало:
Copy code
fun test(objectIds: MutableList<Int>?) {
    val max = objectIds?.max()
    if (max == null) {
        println("true")
    } else {
        objectIds.remove(max)
        println(max)
    }
}
a

Alexjok

04/02/2019, 11:29 AM
Андрей, спасибо за разъяснение! Выглядите лаконичнее) Мысль по поводу изменений листа из других потоков уловил
Жаль нет способа законтрактить, даже если мы сделаем MutableList просто List' ом это все равно не решит проблемы.
g

gildor

04/02/2019, 1:51 PM
Да, само по себе не решит и даже не понятно как такой потенциальный контракт мог бы работать, но в принципе кое что можно сделать, к примеру использовать что-то вроде собственного класса как NonEmptyList, который на уровне системы типов гарантирует что список не пустой и переопределить для него
NonEmptyList<Int>.max(): Int
, тогда такой код будет работать
Другой вопрос насколько оно того стоит
a

Alexjok

04/02/2019, 2:36 PM
Ни насколько 🙂 Спасибо!
3 Views