Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retain smartcast when creating custom extension

Tags:

kotlin

I currently have to write

val myList: List<Int>? = listOf()
if(!myList.isNullOrEmpty()){
    // myList manipulations
}

Which smartcasts myList to no non null. The below do not give any smartcast:

if(!myList.orEmpty().isNotEmpty()){
    // Compiler thinks myList can be null here
    // But this is not what I want either, I want the extension fun below
}

if(myList.isNotEmptyExtension()){
    // Compiler thinks myList can be null here
}

private fun <T> Collection<T>?.isNotEmptyExtension() : Boolean {
    return !this.isNullOrEmpty()
}

Is there a way to get smartCasts for custom extensions?

like image 541
Adam Avatar asked Aug 27 '19 07:08

Adam


People also ask

How do I set retention policies for content?

For retention policies: On the Decide if you want to retain content, delete it, or both page, select Only delete items when they reach a certain age, and specify the time period.

How do I retain content with the primary label?

If you need to initially retain content with the primary label (most typical): On the Define label settings page, select Retain items indefinitely or for a specific period and specify the retention period. Then on the Choose what happens after the retention period page, select Change the label > Choose a label.

How long should I retain my content?

When you configure a retention label or policy to retain content, you choose to retain items for a specific number of days, months (assumes 30 days for a month), or years. Or alternatively, retain the items forever.


1 Answers

This is solved by contracts introduced in Kotlin 1.3.

Contracts are a way to inform the compiler certain properties of your function, so that it can perform some static analysis, in this case enable smart casts.

import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

@ExperimentalContracts
private fun <T> Collection<T>?.isNotEmptyExtension() : Boolean {
    contract {
       returns(true) implies (this@isNotEmptyExtension != null)
    }
    return !this.isNullOrEmpty()
}

You can refer to the source of isNullOrEmpty and see a similar contract.

contract {
    returns(false) implies (this@isNullOrEmpty != null)
}
like image 101
George Leung Avatar answered Oct 17 '22 20:10

George Leung