Kotlin
A concise multiplatform language developed by JetBrains
Kotlin 1.4-M3 is Out: Standard Library Changes
Today we’re glad to present the last milestone preview of Kotlin 1.4 – 1.4-M3. In this post, we’ll guide you through the changes this preview brings to the Kotlin standard library. Other components are also getting updates in M3; we’ll cover them soon in another blog post with the release candidate version (1.4-RC), which will finalize the scope of Kotlin 1.4.
The standard library changes in 1.4-M3 include:
- JVM libraries now come with the
module-info
descriptor - Functional interfaces are added to the standard library
- New collection operations to cover real-life cases
@Throws
annotation in the common library- Deprecation of some functions on floating-point arrays
You can find the complete list of changes in the change log. As always, we’re really grateful to our external contributors.
We would appreciate it very much if you could try the preview and share your feedback.
Standard library artifacts now include module-info descriptors
Starting from Java 9, you can modularize your application thanks to the Jigsaw project. The jlink tool allows you to generate a custom Java runtime image containing only the platform modules that are required for your app. You could use jlink
with Kotlin standard library artifacts before, but you had to use separate artifacts for that – the ones with the “modular” classifier – and the whole setup wasn’t straightforward. The inability to include module descriptors in main artifacts was caused by issues with Android tooling, which have now been fixed.
Kotlin 1.4 adds module-info.java
module information to default standard library artifacts, so you can use them with jlink
with ease. In Android, make sure you use the Android Gradle plugin version 3.2 or higher, which can correctly process jars with module-info.
fun interfaces in the standard library
Kotlin 1.4 supports SAM conversions for Kotlin classes. You can mark an interface with only a single abstract method as a fun interface
, and then pass a lambda as an argument when that interface is expected as a parameter. In the standard library, the following interfaces are now declared as fun interface
‘s:
Comparator
ReadOnlyProperty
PropertyDelegateProvider
(was introduced in 1.4-M2)
You can use a SAM-constructor that takes a lambda as a parameter to create an instance. The resulting code becomes much simpler:
Collection operations
- A new
sumOf
function takes a selector function and returns a sum of its values on all elements of a collection. It is pretty similar to the existingsumBy
andsumByDouble
functions. The key difference is that the newsumOf
function takes selectors with various return types, thus letting you handle sums of different types in the same way. Namely, sumOf produces sums of the typesInt
,Long
,Double
,UInt
,ULong
. On the JVM,BigInteger
andBigDecimal
are also available. -
The
min
andmax
functions have been renamed tominOrNull
andmaxOrNull
. Since their introduction in 1.0,min
andmax
have returnednull
on empty collections. This contradicts the naming convention used across the Kotlin collections API: functions without the*OrNull
suffix throw an exception if the receiver collection is empty. To get anull
instead, you should use the*OrNull
version of the function, for example,firstOrNull
.
Thus, we decided to gradually change the behavior ofmin
andmax
. In 1.4-M3, we’re addingminOrNull
andmaxOrNull
as synonyms formin
andmax
and starting the deprecation cycle formin
andmax
to reintroduce them with non-null return types. -
We’ve introduced
minOf
andmaxOf
functions that return the minimum or the maximum value of the given selector function on the collection items. These functions cover the missing case for which it was required to writemap { selector }.max()!!
ormaxBy { selector }!!.selector
(ormin
andminBy
).For consistency with the existing API, we also added
minOfWith
andmaxOfWith
, which take aComparator
as an argument.
All four new functions follow the non-null convention we described above: they throw exceptions on empty collections and have*OrNull
versions that returnnull
in this case. -
New overloads for
flatMap
andflatMapTo
let you use transformations with return types that don’t match the receiver type, namely:- transformations to
Sequence
onIterable
,Array
, andMap
- transformations to
Iterable
onSequence
- transformations to
-
A new
flatMapIndexed
function has been added as a counterpart forflatMap
. As you may already know,Indexed
in the name of a collection-processing function means that the operation applied has the element index as a parameter.
Common @Throws annotation
Although Kotlin doesn’t have checked exceptions, it uses the @Throws
annotation for interoperability with languages that do have them, such as Java and Swift. Previously, there were separate annotations with this name for JVM (kotlin.jvm.Throws
) and Native (kotlin.native.Throws
).
Starting from 1.4-M3, the
annotation is available as a part of the common library directly in the @Throws
kotlin
package (kotlin.Throws
), which allows you to use it in the common code.
@Throws in suspending functions in Swift and Objective-C
In 1.4-M1, we announced changes in exception handling in Objective-C/Swift interop: now NSError
is thrown only for exceptions that are instances of classes specified as parameters of @Throws
annotation (or their subclasses). In 1.4-M2, we introduced basic support for Kotlin’s suspending functions in Swift and Objective-C. In 1.4-M3, there are small changes in the behavior of suspending functions annotated with @Throws
:
- If you have a
suspend fun
annotated with@Throws
, you need to specifyCancellationException::class
as a parameter of the@Throws
annotation. Otherwise, you will get a compilation error. - If there is no
@Throws
annotation on asuspend fun
, it will implicitly use@Throws(CancellationException::class)
when you call it from Swift.
Equality in floating-point arrays
Many of you know these handy extension functions for container types – contains
, indexOf
, and lastIndexOf
. Some time ago, we figured out that their behavior on floating-point arrays (FloatArray
and DoubleArray
) may be controversial and can seem incorrect.
To be more specific, they use the IEEE 754 standard for floating-point arithmetics. This standard defines the following equality rules for corner cases:
NaN
is not equal toNaN
-0.0
is equal to0.0
Such rules may lead to unexpected results, for example:
Additionally, such behavior is inconsistent with how the same functions work on lists, because they use the total order equality:
In 1.4-M3, we start the deprecation cycle for the contains
, indexOf
, and lastIndexOf
extension functions of FloatArray
and DoubleArray
. When trying to use them, you will see warnings with instructions for replacing the usages of these functions.
In future releases, we’ll tighten the deprecation level to ERROR
and remove these functions from the public API.
Converting from KType to Java Type
In Kotlin 1.3.40, we added a useful typeOf
function to the standard library. This function returns a runtime representation of the given reified type T
as an instance of KType
. However, in many practical use cases, you need to work with the Java reflection java.lang.reflect.Type
objects rather than with KType
s. It was already possible to perform the necessary conversion, but this required using the full kotlin-reflect
dependency. Now we’ve updated the standard library with a way to convert KType
to Java Type
– a KType.javaType
extension property that returns Java Type
:
Note that so far the obtained Java Type
doesn’t behave correctly in some corner cases (like annotated type parameters or declaration-site variance), so KType.javaType
stays experimental. You can find more details about the unsupported cases in this issue.
Compatibility
Note that Kotlin 1.4 is not backward-compatible with 1.3 in some corner cases. All such cases were carefully reviewed by the language committee and will be listed in the “compatibility guide” (similar to this one). For now, you can find this list in YouTrack.
Pre-release notes
Note that the backward compatibility guarantees do not cover pre-release versions. The features and the API can change in subsequent releases. When we reach a final RC, all binaries produced by pre-release versions will be outlawed by the compiler, and you will be required to recompile everything that was compiled by 1.4‑Mx.
How to try the latest features
As always, you can try Kotlin online at play.kotl.in.
In IntelliJ IDEA and Android Studio, you can update the Kotlin Plugin to version 1.4-M3. See how to do this.
If you want to work on existing projects that were created before installing the preview version, you need to configure your build for the preview version in Gradle or Maven.
You can download the command-line compiler from the Github release page.
You can use the following versions of the libraries published together with this release:
- kotlinx.atomicfu version: 0.14.3-1.4-M3
- kotlinx.coroutines version: 1.3.7-1.4-M3
- kotlinx.serialization version: 0.20.0-1.4-M3
- ktor version: 1.3.2-1.4-M3
The release details and the list of compatible libraries are also available here.
Share your feedback
We’re grateful for all your bug reports in our issue tracker, and we’ll do our best to fix all the most important issues before the final release.
You are also welcome to join the #eap channel in ourKotlin Slack (get an invite here). In this channel, you can ask questions, participate in discussions, and get notifications of new preview builds.
Let’s Kotlin!
External contributions
We’d like to thank all of our external contributors whose pull requests were included in this release:
- Toshiaki Kameyama
- Steven Schäfer
- Jinseong Jeon
- pyos
- Mark Punzalan
- rapturemain
- Vitaly Tihonov
- Mads Ager
- Subroh Nishikori
- Juan Chen
- gcx11
- Robert Bares
- Henrik Tunedal
- Nick
- Dmitry Borodin
- Efeturi Money
- Kevin Most
- Anastasiya Krasnoryadtseva
- Kristoffer Andersen
- Martin Petrov
- Matthew Gharrity
- Mike Samuel
- Mikhail Likholetov
- Segun Famisa
- Sinan Kozak
- Vadim Semenov
- Valeriy Vyrva
- Victor Turansky
- Yuku Kotani