BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Kotlin 1.7.0 Beta Enables Definitely Non-Nullable Types

Kotlin 1.7.0 Beta Enables Definitely Non-Nullable Types

Bookmarks

JetBrains has released Kotlin 1.7.0-Beta, enabling builder inference and definitely non-nullable types by default and reintroducing the min(), max(), minBy(), maxBy(), minWidth() and maxWith() functions. Regular expressions now support named capturing groups in Kotlin/JS and Kotlin/Native and allow checking for exact matches at specific positions.

Starting with version 1.7.0, "Milestone" releases are now called "Beta" releases to align with the standard software release life cycle terminology, where "Beta" means that no new features are added and the focus is on stabilizing the features with the help of feedback from the community. To use these new features in version 1.7.0-Beta, configure the build scripts from the Early Access Preview.

Since the release of Kotlin 1.4, the min() and max() collections functions were renamed to minOrNull() and maxOrNull() since they return null when the collection is empty. Comparable functions such as minBy(), maxBy(), minWidth() and maxWidth() were also renamed to include OrNull() at the end of the function name. This latest release reintroduces the min(), max(), minBy(), maxBy(), minWidth() and maxWith() functions, which now return the collection element or throw an exception:

fun main() {
    val intList = listOf<Int>()


    // The following statement prints null
    println(intList.minOrNull())

    // The following statement prints 
    //     "Exception in… Collection is empty."
    println(intList.min())
}

Builder inference is a form of type inference which helps the compiler infer type arguments based on calls inside a passed lambda, without the need for explicit type arguments:

val answerMap = buildMap {
    put("The answer to life, the universe, and everything", 42)
}

The implementation of builder inference was introduced in Kotlin 1.5.30 and this current release enables the fallback builder inference, introduced as a compiler flag in version 1.6, by default whenever regular type inference cannot retrieve enough information for a type. This makes it possible to write custom builders, which use type inference, without any annotations or compiler flags.

Kotlin 1.7.0 automatically enables support for definitely non-nullable types, introduced in Kotlin 1.6.20, to improve interoperability when extending generic Java classes and interfaces. The syntax T & Any may be used to mark a generic type parameter is definitely non-nullable, for example, when overriding a Java method with a @NotNull argument:

// Java method:
@NotNull
public T calculate(@NotNull T x) {}

// Kotlin method:
override fun calculate(x: T1 & Any): T1 & Any

Regex.matchAt() and Regex.matchesAt(), introduced in Kotlin 1.5.30, are now Stable and may be used to verify whether a regular expression matches at a specific position in a String or CharSequence:

myRegex.matchesAt(text, 42) // returns true or false
myRegex.matchAt(text, 42) // returns the match or null

Named capturing groups are now supported on Kotlin/JVM, Kotlin/JS and Kotlin/Native by using the (?<name>group) syntax in a regular expression. The new MatchGroupCollection.get() function may be used to retrieve the text matched by a group by providing the group name:

val regex = "(?<movie>[A-Za-z\\s]+):(?<year>[0-9]{4})".toRegex()
val movie = "The Fellowship of the Ring:2001"

val match = regex.find(movie)!!

// The following statement prints The Fellowship of the Ring
println(match.groups["movie"]?.value)

// The following statements print 2001
println(match.groups["year"]?.value)
println(match.groups[2]?.value)

Group names may also be used when backreferencing groups to match the same text as the capturing group by using the \k<name> syntax. Named groups may be used with replacement expressions, such as the replace() and replaceFirst(), functions where occurrences of ${name} in the replacement string are replaced by captured groups with the same name:

val regex = "(?<movie>[A-Za-z\\s]+):(?<year>[0-9]{4})".toRegex()
val movie = "The Fellowship of the Ring:2001"

// The following statement prints 2001-The Fellowship of the Ring
println(regex.replace(movie, "\${year}-\${movie}"))

The new Kotlin/Native Memory manager is now available as an Alpha release and brings improved performance and developer experience. The new memory manager makes the developer experience when creating cross-platform applications, such as for Android and iOS, easier by removing the differences between the JVM and Native platforms. This solution will become the default option in a future release and may be tested by following the migration instructions.

The Kotlin Blog provides a complete overview of this release and any issues encountered during testing may be reported on YouTrack.

About the Author

Rate this Article

Adoption
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT