Kotlin
A concise multiplatform language developed by JetBrains
Kotlin 1.1-M04 is here!
We are glad to present you the fourth milestone of the upcoming Kotlin release. We’re wrapping up the development of the version 1.1, with the final release planned for Q1 2017. Most features are already in decent shape, so it is a good time to try it and give us your feedback. We will appreciate it a lot!
As with other milestone releases, we give no backwards compatibility guarantees for new language and library features. Anything introduced in milestone releases of 1.1 is subject to change before the final 1.1 release.
Please do share your feedback regarding the new features or any problems that you may run into with this release, via YouTrack, forums and Slack.
This milestone brings a significant rework of coroutine syntax and semantics, making coroutines simpler and more flexible. It also contains standard library enhancements, new language features and compiler plugins, numerous features and improvement in the JS backend, and many other fixes and updates.
The new release also includes all features introduced in the Kotlin 1.0.6, including updates for compatibility with Android Studio 2.3 Beta 1.
The full changelog is available here and some key changes are listed below:
Coroutines
We have significantly re-thought the coroutines design, making it simpler, composable and more powerful:
- All suspending and coroutine builder functions now have intuitive signatures (no more weird transformations to memorise).
- There is only one basic language concept of suspending functions and the corresponding suspending function types. The special
coroutine
keyword was dropped. The coroutine is now simply an instance of a suspendable computation that is started usingstartCoroutine
function from the standard library. - Complex suspending functions can be composed out of more primitive suspending functions. In this release they can tail-call other suspend functions, but this restriction will be lifted in the future.
- Suspending functions can be defined to wrap any callback-style API and can be freely used inside any asynchronous coroutine. The controllers are not needed anymore. The
generate
andyield
pair, that builds synchronous sequences, restricts suspensions inside generate blocks using@RestrictsSuspension
annotation. - Type inference for coroutines is now implemented. You can omit types in most use-cases for coroutine builders and the types will be inferred automatically.
The classical await
suspending function can now be implemented via a tail-call to the suspendCoroutine
suspending function that is a part of the standard library:
suspend fun <T> await(f: CompletableFuture<T>): T = suspendCoroutine<T> { c: Continuation<T> -> f.whenComplete { result, exception -> if (exception == null) // the future has been completed successfully c.resume(result) else // the future has been completed with an exception c.resumeWithException(exception) } }
The corresponding builder is called async
and implemented via the startCoroutine
function:
fun <T> async(block: suspend () -> T): CompletableFuture<T> { val future = CompletableFuture<T>() block.startCoroutine(completion = object : Continuation<T> { override fun resume(value: T) { future.complete(value) } override fun resumeWithException(exception: Throwable) { future.completeExceptionally(exception) } }) return future }
And they can be used together to write a more naturally-looking code with futures:
async { val original = asyncLoadImage("...original...") // creates a Future val overlay = asyncLoadImage("...overlay...") // creates a Future ... // suspend while awaiting the loading of the images // then run `applyOverlay(...)` when they are both loaded return applyOverlay(original.await(), overlay.await()) }
However, futures are just one of many supported use-cases for coroutines. The full overview of the coroutine implementation and their usage samples are available in the revised KEEP document.
We think that now we have got a great design of coroutines for Kotlin, but we realize that it has not been battle-tested enough. Therefore we are going to release it in 1.1 under an opt-in incubation flag. Starting from this milestone you’ll get “This feature is experimental: coroutines” warning when using coroutines. You can turn off this warning with -Xcoroutines=enable
compiler flag or disable this features with -Xcoroutines=error
compiler flag. The corresponding setting is also available under Kotlin compiler settings in the IDEA. To set this option for a gradle project you can add kotlin.coroutines=enable
or kotlin.coroutines=error
to local.properties file at the root of project.
If you are using kotlinx.coroutines library please use updated version 0.2-alpha-1
, adapted to the newest changes in the coroutines design. This version also introduces yieldAll
method in the generate scope. Please see the readme file for further details.
Language features
Type for properties can be inferred from getter
For example in the code below the type for the property foo
will be inferred as String
. See the issue KT-550 for some more details.
val foo get() = ""
Floating point related features, fixes and improvements
Floating point number comparisons now use IEEE 754 compliant comparison where the type is known statically to be Double
or Float
. For ranges of floating point numbers we’ve introduced specialized ClosedFloatingPointRange
interface, which provides its own comparison method, so that extension operations employing ranges, like coerceIn
, could be implemented on top of that. Its instances are obtained with the operator ..
invoked on two Float
or Double
values. See KT-4481 and KT-14651 for details.
Interception of delegated property binding
It is possible now to intercept delegate to property binding using the provideDelegate
operator.
For example, if we want to check property name before binding, we can write something like this:
class ResourceLoader<T>(id: ResourceID<T>) { operator fun provideDelegate(thisRef: MyUI, property: KProperty<*>): ReadOnlyProperty<MyUI, T> { checkProperty(thisRef, property.name) ... // property creation } private fun checkProperty(thisRef: MyUI, name: String) { ... } } fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { ... } class MyUI { val image by bindResource(ResourceID.image_id) val text by bindResource(ResourceID.text_id) }
Here method provideDelegate
will be called in constructor initializer for class MyUI
. So, we can check property consistency at the moment of creation. Earlier such checks were only possible at the moment of calling getter or setter.
Unfortunately, the feature is not yet properly documented, but you can use this draft document as an initial reference.
Enhanced nullability of some JDK methods
Some functions in JDK have a nullability contract defined in the documentation, some do not accept null values, some never return null, and yet others can return null sometimes.
Unfortunately, the JDK does not use any annotations to express such contracts and only states them in the docs. Once before 1.0 we used an external annotations artifact for the JDK which could be supplied to the compiler to alter the signatures of JDK functions, but that approach wasn’t reliable enough.
Now we’re introducing another approach: embedding the information required to enhance the JDK signatures directly into the compiler. As a first step we cover the nullability of a small subset of the API:
java.util.Optional
factory and member functions:of
: that doesn’t allow null valuesofNullable
, it takes a nullable value, and return anOptional
of non-nullable type.get
always return non-nullable value.
java.lang.ref.Reference
and all of its inheritors, likeWeakReference
andSoftReference
:get
returns a nullable value, as it can become null at any moment if the referenced object is garbage collected.
- default methods of JDK’s
Iterator
,Iterable
,Collection
,List
,Map
which are exposed as platform-dependent functions of Kotlin builtin collection interfaces. - java functional types, now they have non-platform types in their invocation methods when they’re constructed with non-platform types.
These enhancements are safe in most cases. In particular, they are safe when the enhanced type becomes more specific (non-nullable) in return position or more general (nullable) in parameter position. But when the type is changed in the opposite direction, the change will be breaking.
We strive not to introduce such breaking enhancements unless not respecting the correct nullability would lead to an exception in runtime. So for example Optional.of
now takes a non-nullable argument which is more restrictive, but trying to pass null
to that method would result in an exception anyway.
On the other hand, we decided not to specify the correct nullability for File.listFiles
which actually can return null sometimes, because in most cases there’s no meaningful fallback other than to throw another exception.
Other changes
- Problem of using a non-public member from a public inline function could now be resolved with the
@PublishedApi
annotation. When it’s applied on an internal member, it becomes effectively public and available to invoke from a public inline function.. See KT-12215 for details. const val
is now inlined at the call site (see KT-11734)- SAM conversions have now the same priority in overload resolution as regular members. That fixes KT-11128 and alike.
- We consider our choice of
mod
name for%
(remainder) operator a mistake with some not so nice consequences (see e.g. KT-14650). Therefore we decided to introducerem
operator, deprecate themod
and provide all tools to make this transition smooth.
Standard library
String to number conversions
There is a bunch of new extensions on the String
class to convert it to a number without throwing an exception on invalid number: String.toIntOrNull(): Int?
, String.toDoubleOrNull(): Double?
etc.
Beware that these functions will box resulting numbers before returning them, as the return type assumes it.
Also integer conversion functions, like Int.toString()
, String.toInt()
, String.toIntOrNull()
, each got an overload with radix
parameter, which allows to specify the base of conversion.
We would like to thank Daniil Vodopian for his substantial contribution to the development of these functions.
onEach
onEach
is a small, but useful extension function for collections and sequences, which allows to perform some action, possibly with side-effects, on each element of the collection/sequence in a chain of operations.
On iterables it behaves like forEach
but also returns the iterable instance further. And on sequences it returns a wrapping sequence, which applies the given action lazily as the elements are being iterated.
Thanks to Christian Brüggemann for the initial prototype.
JavaScript backend
external
instead of @native
From this milestone @native
annotation becomes deprecated and instead you have to use external
modifier.
Unlike the JVM target, the JS one permits to use external
modifier with classes and properties.
Note, that you don’t need to mark members of external
classes as external
: this modifier
is automatically inherited by the members. So, instead of
@native fun alert(message: Any?): Unit {}
you can write
external fun alert(message: Any?)
Improved import handling
You can now describe declarations which should be imported from JavaScript modules more precisely.
If you add @JsModule("<module-name>")
annotation on an external declaration it will be properly imported to a module system (either CommonJS or AMD) during the compilation. For example, with CommonJS the declaration will be imported via require(...)
function.
Additionally, if you want to import a declaration either as a module or as a global JavaScript object, you can use @JsNonModule
annotation
Let’s see the full example below. You can import jQuery library to a Kotlin source file like this:
@JsModule("jquery") @JsNonModule @JsName("$") external abstract class JQuery { fun toggle(duration: Int = 0): JQuery fun click(handler: (Event) -> Unit): JQuery } @JsModule("jquery") @JsNonModule @JsName("$") external fun JQuery(selector: String): JQuery
In this case, JQuery will be imported as a module named jquery
and alternatively, it can be used as a $
-object, depending on what module system Kotlin compiler is configured to use.
You can use these declarations in your application like this:
fun main(args: Array<String>) { JQuery(".toggle-button").click { JQuery(".toggle-panel").toggle(300) } }
You can check the generated JS code for this snippet for the CommonJS and “plain” module systems here.
How to Try It
In Maven/Gradle: Add http://dl.bintray.com/kotlin/kotlin-eap-1.1 as a repository for the build script and your projects; use 1.1-M04 as the version number for the compiler and the standard library.
In IntelliJ IDEA: Go to Tools → Kotlin → Configure Kotlin Plugin Updates, then select “Early Access Preview 1.1” in the Update channel drop-down list, then press Check for updates.
The command-line compiler can be downloaded from the Github release page.
On try.kotlinlang.org. Use the drop-down list at the bottom-right corner to change the compiler version to 1.1-M04.
Merry Kotlin!