New Standard Library API in 1.1

Kotlin 1.1 makes itself suitable for Java 9’s Project Jigsaw

Gabriela Motroc

JetBrains announced less than a week ago that Kotlin 1.1 has reached beta. Now the team has revealed that they are going to make their artifacts more friendly to the Java platform module system.

JetBrains’ Ilya Gorbunov announced in a new blog post that Kotlin is making itself suitable for Java 9’s Project Jigsaw. “One of the constraints [Project Jigsaw] imposes is that no two modules can declare public API in the same package. The situation, when there are two modules that contribute to the same package, is called ‘split’ package.”

According to the announcement, Kotlin faces this issue with split packages in the runtime artifacts: first, kotlin-runtime and kotlin-stdlib modules share a lot of kotlin.* packages, second, kotlin-runtime and kotlin-reflect share kotlin.reflect package. The solution is to make the artifacts more friendly to the module system:

  1. They merge kotlin-runtime and kotlin-stdlib into the single artifact kotlin-stdlib. They will rename kotlin-runtime.jar, shipped in the compiler distribution, to kotlin-stdlib.jar, to reduce the amount of confusion caused by having differently named standard library in different build systems.
    That rename will happen in two stages: in 1.1 there will be both kotlin-runtime.jar and kotlin-stdlib.jar with the same content in the compiler distribution, and in 1.2 the former will be removed.
  2. In kotlin-reflect module all API will be moved from kotlin.reflect to kotlin.reflect.full package. Kotlin 1.1 will have the former API deprecated with the replacements suggested, and it will be removed eventually in 1.2.
    Note that this change will affect only extension functions and properties provided by kotlin-reflect for reflection interfaces and a couple of exception classes. Reflection interfaces themselves are located in the standard library and won’t be moved.

However, those who use maven or gradle and depend on kotlin-stdlib won’t have to change anything. Those who depend on kotlin-runtime are advised to replace that dependency with kotlin-stdlib.

SEE ALSO: Kotlin 1.1 has reached beta

New Standard API Library in Kotlin 1.1

Kotlin 1.1 is not ready yet but it’s coming “fairly soon.” How do we know that? Kotlin 1.1 has finally reached beta.

Let’s take a look at some functions and classes that will be introduced in Kotlin 1.1:

takeIf() and also()

These are two general-purpose extension functions applicable to any receiver.

also is like apply: it takes the receiver, does some action on it, and returns that receiver. The difference is that in the block inside apply the receiver is available as this, while in the block inside also it’s available as it (and you can give it another name if you want).

You can use it when you don’t want to shadow this from the outer scope:

fun Block.copy() = Block().also { it.content = this.content }

takeIf is like filter for a single value. It checks whether the receiver meets the predicate, and returns the receiver, if it does or null if it doesn’t.

Combined with an elvis-operator and early returns it allows to write constructs like:

val outDirFile = File(outputDir.path).takeIf { it.exists() } ?: return false
// do something with existing outDirFile
 
val index = input.indexOf(keyword).takeIf { it >= 0 } ?: error("keyword not found")
// do something with index of keyword in input string, given that it's found
  

groupingBy()

This API is to group a collection by key and fold each group in the same time. It consists of two parts: groupingBy function, and terminal operations — fold, reduce, eachCount.

First you invoke collection.groupingBy { key } function, which just returns a Grouping instance binding the provided key selector to the collection of elements. Then you call one of folding operations available for Grouping, which iterates the collection and populates the resulting map with the result of folding elements in each group.

minOf() and maxOf()

These functions can be used to find the lowest and greatest of two or three given values, where values are primitive numbers or Comparable objects. There is also an overload of each function that take an additional Comparator instance, if you want to compare objects that are not comparable themselves.

Map.getValue()

This extension on Map returns an existing value corresponding to the given key or throws an exception, mentioning which key was not found.

If the map was produced with withDefault, this function will return the default value instead of throwing an exception.

val map = mapOf("key" to 42)
// returns non-nullable Int value 42
val value: Int = map.getValue("key")
// throws NoSuchElementException
map.getValue("key2")
 
val mapWithDefault = map.withDefault { k -> k.length }
// returns 4
val value2 = mapWithDefault.getValue("key2")
 

Map.minus() operator

In Kotlin 1.0 you could easily get a copy of a read-only Map with a new key-value pair inserted with the extension operator Map.plus(). However to remove a key from the map you have to resort to less straightforward ways to like Map.filter() or Map.filterKeys().

Now Map.minus() operator fills this gap. There are 4 overloads available: for removing a single key, a collection of keys, a sequence of keys and an array of keys.

val map = mapOf("key" to 42)
val emptyMap = map - "key"

Array-like List instantiation functions

Similar to the Array constructor, there are now functions that create List and MutableListinstances and initialize each element by calling a lambda:

List(size) { index -> element }
MutableList(size) { index -> element }
 

The list also includes string to number conversions, onEach(), Map.toMap() and Map.toMutableMap() and abstract collections.

You can find here the entire list of functions and classes.

Author
Gabriela Motroc
Gabriela Motroc is an online editor for JAXenter.com. Before working at S&S Media she studied International Communication Management at The Hague University of Applied Sciences.

Comments
comments powered by Disqus