Kotlin 1.7.0-Beta Released
The first preview of the 1.7.0 release is out. Introducing Kotlin 1.7.0-Beta! This preview includes:
- Changes to builder inference.
- The return of the min() and max() collection functions.
- Stabilizing of definitely non-nullable types.
- Updates for the new Kotlin/Native Memory Manager.
Install 1.7.0-Beta to try out these features and report any issues you find to help us improve Kotlin 1.7.0.
Starting from 1.7.0, we’re updating our cadence terminology by changing “Milestone” to “Beta”. There are a few reasons behind this decision:
- We want the Kotlin builds terminology to be more aligned with the standard terminology of the software release cycle. To put it more precisely, “Beta” means we’re done adding new features to that specific version and are working on stabilization. Though the final changes will be implemented, including changes based on your feedback.
- Some time ago, M-release compilers were producing “pre-release” code, which made these versions harder to test. This is no longer the case. We want to avoid any confusion and emphasize that trying out Kotlin Beta versions is a simple process and highly encouraged by the Kotlin team.
- Last but not least, the term “Beta” itself is a call for feedback from the community. We use it to let you know we want you to share feedback with us.
Please evaluate Kotlin 1.7.0-Beta and share your feedback with us on YouTrack and Slack (for new Slack members: apply to be invited).
Changes to builder inference
Builder inference is a special kind of type inference that is useful when calling generic builder functions. It helps the compiler infer the type arguments of a call using the type information about other calls inside its lambda argument.
Kotlin 1.7.0-Beta includes further changes to builder inference. It brings us closer to builder inference stabilization and completion of one of the items on our roadmap.
With this release, builder inference is automatically activated if a regular type inference cannot get enough information about a type without specifying the -Xenable-builder-inference
compiler option, which we introduced in version 1.6.0.
This means that now you can write your own builders that use builder type inference without applying any additional annotations or options. Learn how to write custom generic builders.
The return of the min() and max() collection functions
In Kotlin 1.4, we renamed the min()
and max()
collection functions to minOrNull()
and maxOrNull()
. These new names better reflect their behavior – returning null
if the receiver collection is empty. It also helped to align the functions’ behavior with naming conventions used throughout the Kotlin collections API.
The same was true of minBy()
, maxBy()
, minWith()
, and maxWith()
, which all got their *OrNull()
synonyms in Kotlin 1.4. Older functions affected by this change were gradually deprecated.
Kotlin 1.7.0-Beta reintroduces the original function names, but with a non-nullable return type. The renewed min()
, max()
, minBy()
, maxBy()
, minWith()
, and maxWith()
now strictly return the collection element or throw an exception.
fun main() { val numbers = listOf() println(numbers.maxOrNull()) // "null" println(numbers.max()) // "Exception in… Collection is empty." }
See this YouTrack issue for details.
Stabilizing of definitely non-nullable types
Kotlin 1.7.0 will have stable definitely non-nullable types, which were introduced in Kotlin 1.6.20.
These types have been added to provide better interoperability when extending generic Java classes and interfaces.
Since Kotlin 1.6.20, you’ve been able to mark a generic type parameter as definitely non-nullable on the use site with the new syntax T & Any
. The syntactic form comes from a notation of intersection types and is now limited to a type parameter with nullable upper bounds on the left side of &
and non-nullable Any
on the right side:
funelvisLike(x: T, y: T & Any): T & Any = x ?: y fun main() { elvisLike ("", "").length // OK elvisLike ("", null).length // Error: 'null' cannot be a value of a non-null type elvisLike (null, "").length // OK elvisLike (null, null).length // Error: 'null' cannot be a value of a non-null type }
Definitely non-nullable types are enabled by default in this Beta release. No additional steps are required.
Learn more about definitely non-nullable types in the KEEP.
Matching with Regex at a particular position
The Regex.matchAt()
and Regex.matchesAt()
functions, introduced in 1.5.30, are now Stable. They provide a way to check whether a regular expression has an exact match at a particular position in a String
or CharSequence
.
matchesAt()
checks for a match and returns a boolean result:
fun main(){ val releaseText = "Kotlin 1.7.0 is on its way!" // regular expression: one digit, dot, one digit, dot, one or more digits val versionRegex = "\d[.]\d[.]\d+".toRegex() println(versionRegex.matchesAt(releaseText, 0)) // "false" println(versionRegex.matchesAt(releaseText, 7)) // "true" }
matchAt()
returns the match if it’s found, ornull
if it isn’t:
fun main(){ val releaseText = "Kotlin 1.7.0 is on its way!" val versionRegex = "\d[.]\d[.]\d+".toRegex() println(versionRegex.matchAt(releaseText, 0)) // "null" println(versionRegex.matchAt(releaseText, 7)?.value) // "1.7.0" }
We’d be grateful for your feedback in this YouTrack issue.
Updates of new Kotlin/Native Memory Manager
You can try the Alpha version of the new Kotlin/Native memory manager in Kotlin 1.7.0-Beta. This release brings performance improvements to the new memory manager that will improve the developer experience.
The new memory manager eliminates the differences between the JVM and Native platforms. It provides a consistent developer experience in multiplatform projects. For example, you’ll have a much easier time creating new cross-platform mobile applications that work on both Android and iOS.
The new Kotlin/Native memory manager lifts restrictions on object-sharing between threads. It also provides leak-free concurrent programming primitives that are safe and don’t require any special management or annotations.
The new memory manager will become the default one in future versions, so we encourage you to try it now. Learn more about the new memory manager and explore demo projects, or jump right to the migration instructions to try it yourself.
Try using the new memory manager on your projects to see how it works and share your feedback in our issue tracker, YouTrack.
Support for named capturing groups in JS and Native
Since Kotlin 1.7.0-Beta, named capturing groups are supported not only on the JVM (1.8 and later) but on JS and Native as well.
To give a name to a capturing group, use the (?
syntax in your regular expression. To get the text matched by a group, call the newly introduced MatchGroupCollection.get()
function and pass the group name.
Retrieve matched group value by name
Consider this example for matching city coordinates. To get a collection of groups matched by the regular expression, use groups
. Compare retrieving a group’s contents by its number (index) and by its name using value
:
fun main() { val regex = "\b(?[A-Za-z\s]+),\s(? [A-Z]{2}):\s(? [0-9]{3})\b".toRegex() val input = "Coordinates: Austin, TX: 123" val match = regex.find(input)!! println(match.groups["city"]?.value) // "Austin" — by name println(match.groups[2]?.value) // "TX" — by number }
Named backreferencing
You can now also use group names when backreferencing groups. Backreferences match the same text as previously matched by a capturing group. For this, use the k
syntax in your regular expression:
fun backRef() { val regex = "(?\w+), yes \k ".toRegex() val match = regex.find("Do you copy? Sir, yes Sir!")!! println(match.value) // "Sir, yes Sir" println(match.groups["title"]?.value) // "Sir" }
Named groups in replacement expressions
Finally, named group references can be used with replacement expressions. Consider the replace()
function that substitutes all occurrences of the regular expression in the input with a replacement expression, and the replaceFirst()
function that swaps the first match only.
Occurrences of ${name}
in the replacement string are substituted with the subsequences corresponding to the captured groups with the specified name. Compare replacements in group reference by name and by index:
fun dateReplace() { val dateRegex = Regex("(?
Try new features and provide feedback
These new features are available in the 1.7.0 preview release, Kotlin 1.7.0-Beta. You can easily install it in your IntelliJ IDEA or Android Studio IDE.
Due to Android Studios plugins renaming (Beta), plug-in installation is available on top of 1.6.20+ versions.
Install Kotlin 1.7.0-Beta in any of the following ways:
- If you use the Early Access Preview update channel, the IDE will suggest automatically updating to 1.7.0-Beta as soon as it becomes available.
- If you use the Stable update channel, you can change the channel to Early Access Preview at any time by selecting Tools | Kotlin | Configure Kotlin Plugin Updates in your IDE. You’ll then be able to install the latest preview release. Check out these instructions for details.
You can always download the latest versions of these IDEs to get extensive support for Kotlin:
- IntelliJ IDEA for developing Kotlin applications for a variety of platforms.
- Android Studio for developing Android and cross-platform mobile applications.
Once you’ve installed 1.7.0-Beta, don’t forget to change the Kotlin version to 1.7.0-Beta in your build scripts.