What’s new in Standard Library M13 and M14

Ilya Gorbunov

Standard Library continues its evolution:

  • Lazy<T> type has been introduced
  • More concise syntax for storing properties in a Map
  • Final changes in the Char arithmetics
  • Plus and minus operations on a collection now depend on its type
  • New scope functions: apply and run
  • Right-open ranges
  • Trimming indents in multiline strings literals
  • and more

What’s new in M13


Lazy evaluation is a useful pattern and it was unfair to limit it only to delegated properties. Now there is Lazy<T> type right in the kotlin package and you can use it in many contexts. You can delegate properties to instances of Lazy, which has the get extension function to satisfy the delegation convention:

class Poll(val json: Map<String, *>) {
    val messages: List<Message> by lazy {
        // some expensive and not always needed computation
        val field = json.get("messages")
        (field as JSONArray).toList().map {
            Message((it as JSONObject).toMap())

Unlike Delegates.lazy, an semantics of lazy is synchronized by default.

Delegating properties to a map

Another common use case is storing values of properties in a map, where names of properties serve as keys. For this case we provide extension functions get and set on maps to satisfy the delegation convention, allowing to delegate property right to the map, without creating wrapper delegate objects:

import kotlin.properties.*

class Poll(val json: Map<String, *>) {
    val timestamp: Long by json
    val utc_timestamp: Long by json
    val error: String by json

Observable and vetoable properties

We have fixed a nuisance with observable delegates: the callback handler passed to observable property was called before the property value was changed. Now it is invoked after. It’s worth noting that callbacks are now inlined into these delegates, thus usages of observable and vetoable delegates now cost one object allocation less.

Read more about standard delegates in the reference.

Completing the change of Char arithmetic

In M13 we’re finalizing the semantic changes of arithmetic operations on the Char type. Only three arithmetic operations on Char are left:

  • Char - Int → Char
  • Char + Int → Char
  • Char - Char → Int

All other binary operations involving Char were deprecated in M12 and now are dropped.

Plus and minus operators for collections

plus operation on collections is not new, but it was defined so that its return type and behavior were not intuitive: for example, when adding an element to a set, you would receive a list having that element concatenated to all elements of the set, possibly resulting in that element to be duplicated.
Now return type of plus operation depends on the type of first operand:

  • for Iterable, Collection and List the result is List, and operation is a concatenation
  • for Array the result is Array, and operation is concatenation
  • for Set the result is Set, and operation is inclusion of element(s) into the resulting set
  • for Map the result is Map, and operation is inclusion of key-value pair(s) into the resulting map
  • for Sequence the result is Sequence, and operation is lazy concatenation

Also we have introduced minus operation. It has the same relation between type of its first operand and its return type, and the following semantics:

  • Collection - single_element returns the collection with the single occurrence of that element removed
  • Collection - collection_of_elements returns the collection without all the elements contained in another collection.

New scope functions: apply and run

Prior to M13 there were two so-called scope functions in the Standard Library: let and with. We call them scope functions, because their only purpose is to modify scope of a function passed as the last parameter. For example, to bring the parameter of scope function to the receiver of function parameter in case of with, and vice versa in case of let.
Now you have two more scope functions at your disposal:

  • one that passes its receiver to the receiver of its function parameter:
    T.run(f: T.() → R): R
    We call it run, because it’s a generalization of run without receiver.
  • one that applies given Unit-returning function to the receiver and returns the receiver itself:
    T.apply(f: T.() → Unit): T

Constructing open ranges

There was a common request to introduce right-open ranges in Kotlin. We have examined use-cases and found that most of them are involving integer ranges. In case of integers an opened at the end range can be represented with a closed range, whose end value is one less than the corresponding open range’s end.
To create such ranges you can use newly introduced until function. It returns closed range with values up to the specified end but not including it, so that:

0 until 20 == 0..19

find vs firstOrNull

There were many debates about naming a function that finds the first element matching given predicate in a collection. find is easy to explore, but firstOrNull is consistent with how this operation is called in LINQ and Reactive Extensions. Prior to M13 find was deprecated in favor of firstOrNull, but now we’ve decided to “undeprecate” it and leave as a synonym for firstOrNull. Also we’ve provided findLast, which is a synonym for lastOrNull.

Removing indentation from multiline string literals

A well-known pain with multiline string literals was the formatting: you couldn’t format a code containing these literals well without introducing whitespace into the literal itself.

    val multiline = """First line
Second line
Third line"""

Now we provide several functions to strip common whitespace prefix from each line of a string:
trimIndent, trimMargin, replaceIndent, replaceIndentByMargin

    // first and last blank lines are removed, 
    // and common indentation from other lines is stripped
    val multiline = """
      First line
      Second line
      Third line

Dropping deprecated API

In M13 we have dropped some of previously deprecated APIs: streams, extension methods for iterators, FunctionalList, FunctionalQueue and StringTemplate.

The full list of changes is available here.

Plans for M14

Distributing top-level functions between package parts

As we have announced earlier we’re changing the way how top-level functions and properties are mapped to class files in compiled code. In the next milestone all the top-level stuff in Standard Library is going to be distributed between corresponding package parts. We’ll keep the KotlinPackage facade class that contains all top-level functions, but it will be deprecated and removed in the future.

Note that these changes only affect usages of top-level Kotlin members from Java code. An inspection in the IDE will be provided to migrate these usages.

What’s going to be dropped next

We’re still in the process of cleaning up deprecated APIs from the Standard Library and here is the list of what we are going to drop in the next milestone:

  • size, empty and notEmpty extension properties;
  • extensions makeString and appendString;
  • methods to construct arrays and collections from provided elements: array, intArray, arrayList, hashMap, etc.

kotlin-swing and kotlin-jdbc status

There were two experimental libraries: kotlin-swing and kotlin-jdbc. We’re not going to ship them anymore to the Maven Central repository. Last versions published to Maven would be compiled against M14.

If you depend on these libraries feel free to fork their source code and compile them locally. We have extracted them from the Kotlin codebase into separate repositories on GitHub under kotlin-projects organization:

Comments below can no longer be edited.

18 Responses to What’s new in Standard Library M13 and M14

  1. Zdenek says:

    September 28, 2015

    Changes looks nice, but when do you plan to release 1.0? Do you think you will make it this year or it will be postponed to the 2016?

    • Roman Belov says:

      September 28, 2015

      It’s hard to give the estimates, but we are working hard to release 1.0 as soon as possible.

      • Zdenek says:

        September 28, 2015

        I know, but very roughly… do you think it is real release this year or somewhere 2016 is closer to the reality?

        • Jayson Minard says:

          September 28, 2015

          I think the language is ready for 1.0, recent blog posts indicating that last changes needed to be done soon before 1.0, and behaviour of releases indicates that it is imminent. I’m hoping for 1.0 this year.

          • ruX says:

            September 30, 2015

            Not really. Every next update has a breaking changes – it’s not normal developer expect from programming language

  2. Zlonax Bubuka says:

    September 28, 2015

    Do you consider Kotlin->Java translator? For example, GWT would benefit from it.

    • Andrey Breslav says:

      September 28, 2015

      No, we are not planning on implementing such a translator, but Kotlin is OSS, and anybody who finds it beneficial can start such a project

  3. Oleg (Kotlin fan) says:

    September 28, 2015

    Thank you so much for your work! You make life of many developers much easier!

  4. MuppetGate says:

    September 29, 2015

    I’m not sure that until keyword is particularly intuitive. If I see 0 until 20 then I expect the value to run from 0 to 20.

    • Christian Brüggemann says:

      September 29, 2015

      I really wonder why IntRanges aren’t open ended by default anyway. That would follow the standard Java semantics, see String.substring(x, y) for example.

    • Peter Niederwieser says:

      September 29, 2015

      For what it’s worth, Scala also uses until for exclusive upper bound.

  5. Neil says:

    September 30, 2015

    If a plus operation on an Iterable returns a List, does that mean the iterator was iterated all the way through to construct the List?

    Why not cons up a new Iterable that first delegates to the old iterator then when old one has finished returns the new item?

    That way no copy is made, and the original Iterable is evaluated lazily (as you seem to be saying for Sequence).

    • ilya.gorbunov says:

      October 1, 2015

      We had thought about this operation and decided to give it eager behavior as most of operations on iterables in standard library have.
      For lazy evaluation we provide sequences. You can convert an Iterable to Sequence with asSequence extension function.

      • Neil says:

        October 1, 2015


        Thank you for the additional detail.


  6. chushuhuch says:

    October 1, 2015

    Open ranges improve iterating experience. But I can’t find any discussions (and maybe it’s already too late) about why C-style loops are not supported. Do you suppose most of the cases are covered with ranges?

    • Andrey Breslav says:

      October 1, 2015

      Yes, we do. Our experience shows that C-style for loops are not really needed (in the very rare cases where for doesn’t work, while is enough)

      • chushuhuch says:

        October 2, 2015

        OK. Personally I do rather often write loops with incremented counter which have dynamic break condition. And also simultaneous iteration (both parallel and from two ends) seems to occur relatively often. Maybe there are some tricks which I don’t realize?

        • Andrey Breslav says:

          October 6, 2015

          Well, I think there should be ways of expressing that through ranges etc, but we’d need to look into particular use cases to find exact solutions. In any case, such use cases do not seem to be very typical in most projects.