Thread
#stdlib
    l

    Leon K

    2 years ago
    small stdlib proposals to improve smart-casting concerning nullability: we need a way to do
    if(foo != null)
    for multiple values and collection contents. Proposal part one add a
    ifNotNull
    function that takes vararg arguments of type
    Any?
    . given
    val a: Int? = 1
    val b: String? = null
    val c: Boolean? = false
    this would allow to replace this:
    if (a != null && b != null && c != null) {
        println("$a, $b, $c")
    }
    with this:
    ifNotNull(a, b, c) {
        println("$a, $b, $c")
    }
    which imo is a lot more readable, and also easier to type. (small note/question: would these checks - if the function was just implemented in terms of contracts and the if-statement - short-circuit, like they do with the if-statement?) proposal part two higher-order-functions on collections should do smart-casting. (I guess this should be doable via contracts?) given
    fun useList(nums: List<Int>) = println(nums)
    val foo: List<Int?> = listOf(12, 13, null, 14)
    this would allow to do something like this:
    if (foo.all { it != null } ) {
    	useList(foo)
    }
    currently, afaik, this check is not possible with compiler-guarantees, as there is no
    Collection<T>.hasNoNulls()
    check. there are some simmilar functions, but nothing that actually does this. there is-
    Iterable<T?>.requireNoNulls()
    - the most simmilar, but this throws exceptions and isn't as general as making
    all
    and
    any

    -calls smart-cast

    Iterable<T?>.filterNotNull()
    - could be currently used in combination with the all-check to "simulate" a smart-casting all, but as it just filters out the null-values, this could to easily be broken if someone isn't careful when modifiying the preceding if-statement.
    karelpeeters

    karelpeeters

    2 years ago
    You can't really implement this in the stdlib yet, the closest you could get is having lots of overloads for all possible arguments counts:
    fun notNull(a: Any?, b: Any?, c: Any?): Boolean {
        contract { returns(true) implies (a != null && b != null && c != null) }
        return a != null && b != null && c != null
    }
    l

    Leon K

    2 years ago
    i'm not too confident with my knowledge about the contract-API, but couldn't you do it via vararg, and then do the checks via .all or something, and then specify in the contract that
    returns(true) implies (args is Array<T>)
    (where args is
    vararg args: T?
    ? or why would this not work?
    n

    nkiesel

    2 years ago
    the real problem with ifNotNull(IMHO better named noneNullis that it evaluates all parameters first. Thus,
    noneNull(a, b, b.c)
    will not work. You would have to use noneNull(a, b?.c)instead but in my experience (I tried that) this leads to more problems than it solves
    l

    Leon K

    2 years ago
    thats a valid concern,... so this would need to be implemented on a language level to allow for short-circuiting and such, correct?