Может ли контракт Kotlin подразумевать невозможность обнуления всех vararg-аргументов функции?

Я хотел бы написать функцию верхнего уровня следующим образом:

      @ExperimentalContracts
fun containsNull(vararg objs: Any?): Boolean {
    contract {
        returns(false) implies (/* ???? */)
    }
        
    for (o in objs) if (o == null) return true
        
    return false
}

так что я могу компилировать такой код без ошибок

      if (containsNull(value1, value2, value3)) return

doSomething(value1.myProperty) 
/* and similar calls multiple times, without the need to use the "?." operator */

но, кажется, нет возможности заполнитьдля достижения этого, потому что информация об отдельных аргументах теряется при их преобразовании в итерируемую коллекцию, предоставляемую ключевым словом vararg, и нет способа сообщить компилятору, что все эти аргументы безопасно не равны нулю.

Таким образом, единственный способ добиться этого - создать несколько функций, таких как:

      containsNull(obj1: Any?, obj2: Any?)
containsNull(obj1: Any?, obj2: Any?, obj3: Any?)
etc...

и подразумевают невозможность обнуления для каждого отдельного аргумента в каждом отдельном контракте.

ИЛИ вместо того, чтобы писать функции, делать что-то вроде этого

      try {
   value1!!
   value2!!
} catch (e: NullPointerException) {
   return
}

doSomething(value1.myProperty)

который немного меньше загромождает, чем каскади быстрее писать, но выглядит излишним.

Я правильно угадываю? Есть ли более краткий и чистый способ обойти это?

1 ответ

На данный момент кажется, что невозможно достичь решения с помощью комбинацииvarargи контракты, поэтому я остановился на подходе функций. В одном файле я поставил подписку на контракты вверху

      @file:OptIn(ExperimentalContracts::class)

затем я объявил все функции. В качестве примера вот тот, который принимает 5 параметров

      fun oneOrMoreIsNull(
    obj1: Any?,
    obj2: Any?,
    obj3: Any?,
    obj4: Any?,
    obj5: Any?
): Boolean {
    contract {
        returns(false) implies (
            obj1 != null &&
            obj2 != null &&
            obj3 != null &&
            obj4 != null &&
            obj5 != null
        )
    }
    
    return obj1 == null || obj2 == null || obj3 == null || 
           obj4 == null || obj5 == null
}

Затем я могу вызвать функцию, и умное приведение правильно обнаружит ненулевые значения.

      if (oneOrMoreIsNull(arg1, arg2, arg3, arg4, arg5)) return

// All these examples now don't require null checking.
arg1.fancyComputation()
if (arg2.isValid()) doSomething()
doSomeMath(arg3.value, arg4.value)
Другие вопросы по тегам