Java puts out a decent feature release every 6 months. Kotlin also puts out a feature release about twice a year, but there seems to be a lot less going on. The “big” feature of 1.3 was promoting an existing feature (coroutines) to stable, and 1.4 has so little that JetBrain’s blog post mostly talked about what they’re planning to do in the future. There were some nice little things added in both releases, but no big jumps like we get with Java (switch, type inference etc.)
Am I missing something? Is it because I’m only interested in Kotlin/JVM, I’m just not in the target market for current Kotlin development?
It’s true that there haven’t been any flashy features since coroutines, but promoting them to stable was a big step IMO, since for many companies that the earliest point they become viable. 1.4 on the other hand is mostly focused on small things and compiler improvements as well as multiplatform.
They’ve been working on a complete rewrite of the type inference and are working on a complete compiler rewrite to increase compile speed and alow for more flexibility in the future.
My guess is that this is a necessary step before adding more complex features and will also probably speed up development since the different platforms are more streamlined.
Also there are 2 big features since 1.3 that you missed in your summary. Inline classes and contracts. Both still experimental but this shows that there is still ongoing work on new features.
My guess is that after the compiler rewrite is finished JetBrains will work on finishing those features as well as maybe adding pattern matching or taking a look at keep 87 (compile time extension interfaces) or keep 176 (compound extensions), but this is just a guess. Who knows maybe they have some other great feature idea that we don’t know about.
Apart from all that there has been done a lot of work on multiplatform and native, mainly on the library side I think, but I mostly use kotlin jvm so I’m not entierly sure the exact focus there.
I wrote a similar post more than a year ago shortly after the Kotlinconf 2018. Guess what, it feels like there was no progress at all.
I understand that there is lots of progress under the hood in improving and fixing underlying systems. Also I understand the importance of native and multiplatform, but they are quite niche currently. It might not be enough to keep people interested, certainly not enough for the classical JVM Backend Developer.
Compare it with Oracle’s information policy. They have outlined language features for the next 3-4 years. Those Java features are very exciting to talk about. See Jake Wharton’s Kotlinconf 19 talk for a comprehensive summary of new Java features in the next 3 years.
From jetbrains there is no information whatsoever. I don’t necessarily need to know when a feature will be available. But we don’t even know which KEEPs will be accepted. Those 2 KEEPs that @Wasabi375 linked to? We don’t even know whether Jetbrains wants to implement them, let alone what the time frame for them is. There is no official public word from Jetbrains other than some comments in some KEEPs that are often several years old.
Disclaimer: I am working on a project that uses multiplatform Kotlin JVM/JS with extensive use of coroutines, kotlinx-serialization and kotlinx-html libraries. All of those tools and libraries had great progress within the last year. IntelliJ integration also gets better for those regularly. I am very grateful for that. I just wish there were more exciting progress on the language level. Or at least some information openness similar to Oracle’s.
There was a talk on KotlinConf about java “catching up”. You can probably see it as soon as recordings are ready.
Kotlin team is fully commited to the new compiler now as well as releasing some necessary multiplatform libraries like kotlinx-io. I had a few short discussions with different people during KotlinConf and they confirmed that they will return to features when new compiler and IR are in play. Currently it does not make any sense to add those features since they will need to reimplement them anyway.
One of the ways to implement multiple receivers is definitely one of main concerns. KEEP-87 seems to be the beaten and safe track. It is tested by Arrow team and has a lot of supporters from Haskel/Scala world. On the other hand, KEEP-176 (with the changed syntax, mind you, I do not like the proposed one) is in my opinion much more beautiful and powerful (if you take file-level and class-level receivers as well), but it is something new and specific to Kotlin, so committee will need some convincing about it. I will spend some of my time on improving the proposal, but I would like to ask everyone, who likes it, to contribute to the discussion. The specific point, we need to understand better (and to convince Breslav, because he is not sure, we fully understand every problem) is the resolution rules, which I have written here.
Yes, I have seen the Java19 talk by Jake in the Kotlinconf livestream. Jake tried to convince that Kotlin will not end, but ultimately didn’t give any compelling reasons. Of course, Kotlin will not end, but it would have been nice to see a plan.
Thanks for sharing your information @darksnake. The argument about saving double work is a good one. Enough to calm me down. Let’s hope the new compiler will be ready soon. I heard that it will not be completed for Kotlin 1.4.
Yes, I do I like KEEP-176 more than KEEP-87. And I am already following both those KEEPs and adding my thoughts whenever there is opportunity. Especially class-level extensions would be a huge improvement for a context-aware programming pattern that we already utilize in our project at work.
I think that the whole Jetbrain teams did an outstanding job. Kotlin is a huge box of moving parts: IDE integration, three compilers, the standard lib with three targets, gradle support for MPP, JS, Native, the various kotlinx libraries like coroutines and serialization. They made a lot in a very short time (at pretty good quality) and it’s only natural that they need time to stabilize.
As far Java catching up goes I wouldn’t worry to much about it. Java has a long way to go to becoming actually expressive and clean and some of it’s outdated design is going to be pretty hard to get rid of. Also I don’t see them ever adding something as contested as operator overloading.
And if Java catches up so what? A little competition can be quite invigorating
I think most people here agree with you that JetBrains has done an outstanding job so far and I also agree that there is nothing to worry about (yet) with java catching up. As you said java has still a long way to go and I don’t think that kotlin is going to stay the way it is right now without improving.
That said I understand some of the frustration with the lack of information about the future. I think this is one area where the kotlin team can improve. As @fatjoe79 mentioned there is no information about what KEEPs are favoured by JetBrains (comparing 176 and 87) and maybe they haven’t decided yet, but that would also be something that they could tell us about.
I also think that 1.4 is not the version for new features. Building a new compiler that combines all platforms and fixing underlying issues is important and should be done before new features are added, but I’m pretty sure that the kotlin team has plans for 1.5 already, why not give us some hints at least.
I know talking about features get’s interpreted as a promise of said feature in many cases but I think most people would understand if they say “We are considering this and that, but we can’t promise anything yet”. That at least would give some information about the future.
Lastly this sounds super critical of the kotlin team and I want to end by saying that I love kotlin and I think they are doing a great job. This is just something that they can improve on.
I now watched the end panel of Kotlinconf 2019. Some interesting answers given by @abreslav:
On whether they have new language features on the table: yes they have many ideas on the table, but rather on the end of the table, and the table is very very long.
On whether they decided already what will be included in 1.5: no they have not planned 1.5 yet at all.
What about type classes: they know about the use cases and are looking into it, but didn’t decide yet which solution (KEEP?) it will be.
Java has planned pattern matching several years down the road. Is this something they could imagine for Kotlin also: Conditionally. If Java ever ships pattern matching, they will look into how it worked out for Java. It is a very complicated feature, and they like the idea of letting others implement the feature first. Unfortunately there was no mention of Scala’s pattern matching feature, which exists since more than 10 years and is very similar to how Java has planned it.
I agree with you. There’s a lot of things going on with Kotlin Native and Kotlin multiplatform. I’m using JVM and I’m just not interested with those developments. Even Kotlin JS is not very interesting for me, because there’s no comparable frameworks to React or Angular for Kotlin, so I’ll have to stick with TypeScript anyway for frontend. And for Kotlin JVM there’s not a lot of exciting things going on and nothing even promised. It was an easy choice between Java and Kotlin few years ago. It’s not so easy now. Google chosen Kotlin as their preferred language, but I feel that it’s more about their battles with Oracle. And for backend Java code it’s a different situation.
Java does not currently has or has robust plans for actual patter matching. All it has is a glorified switch, which is less functional then existing when in kotlin. What Breslav was talking about is that it makes sense to think about actual pattern matching when Java will actually have some kind of proposal about it.
Let’s not get into arguments what “planned feature” means. Oracle is definitely playing around with the idea to introduce nestable pattern matching, similar to how Scala has it. Sure, it is a long-term idea. They think about introducing it step-by-step, with glorified switch expressions being one of the first steps. At the end, it would look something like this:
int eval(Node n) {
return switch(n) {
case IntNode(var i) -> i;
case NegNode(var n) -> -eval(n);
case AddNode(var left, var right) -> eval(left) + eval(right);
case MulNode(IntNode(0), var right),
MulNode(var left, IntNode(0)) -> 0;
case MulNode(var left, var right) -> eval(left) * eval(right);
};
}
His words are clear on this in the Kotlinconf end panel:
“If Java ever ships pattern matching, we will consider something like this. It really is kind of a difficult and risky feature. I’d really like somebody else to try it before me.” (ignoring Scala’s pattern matching)
You can see this answer in minute 9:17:25 in this video:
I was there, I remember. The thing is that Java is not even close to fully implementing Amber ideas. There are not robust proposals so far. I am not sure about Scala. From a glance in documentation, it seems that it can’t do anything new compared to Kotlin when + smart casts. And I would like to see use-cases anyway.
Think about the Visitor Pattern, and its use cases. The visitor pattern becomes somewhat obsolete, as its use cases can most often be solved in a more concise way with pattern matching. Sure, in many of those use cases smart casts do a good job, too. But you can easily think about examples that would be quite boilerplate-y with Kotlin’s traditional when+smartcast. See the example that I have shown above for a starter.
Kotlin:
fun eval(n: Node): Int = when(n) {
is IntNode -> n.intValue
is NegNode -> -eval(n)
is AddNode -> eval(n.left) + eval(n.right)
is MulNode -> if ((n.left as? IntNode)?.intValue == 0 || (n.right as? IntNode)?.intValue == 0) {
0
} else {
eval(n.left) * eval(n.right)
}
}
Java with pattern matching:
int eval(Node n) {
return switch(n) {
case IntNode(var i) -> i;
case NegNode(var n) -> -eval(n);
case AddNode(var left, var right) -> eval(left) + eval(right);
case MulNode(IntNode(0), _) -> 0,
case MulNode(_, IntNode(0)) -> 0;
case MulNode(var left, var right) -> eval(left) * eval(right);
};
}
You can easily think about ways to add more useful simplification rules to this code which make it more and more complex in Kotlin without affecting the Java complexity much. The example would have been better if it did not evaluate the node, but instead would return a new simplified Node that will evaluate to the same value.
My two cents: like others here, I also feel we are missing in the Kotlin world a vision, or at least the communication of the vision. This is something I really miss from the Java world, where we consistently have the feeling of seeing the future built in front of our eyes, with all the great projects with regular progress made and communicated (including Amber, Loom, Valhalla, Panama, etc); even every six-month releases are packed with gorgeous changes, just look at JDK 14!
On the other hand, Kotlin is really great and Jetbrains teams have been doing an outstanding job in so many directions at once, in so little time, so my comments should not be taken negatively, thanks for the awesome work! But apart from this keynote which talks a bit about 1.4 and next versions (yeah a faster compiler, that’s really good!) with vague details though, there is very little vision communicated, and KEEPs are often outdated with no indication of their priority or progress. Of course I may have missed some communication channel, but I have looked and couldn’t find anything, so if it exists it’s well hidden.
I know the Kotlin world is yet much smaller and a bit young to have as many advocates and communicants as Java, but I feel like it wouldn’t take that much to make us all happy: maybe a yearly or bi-yearly blog with an update on the high level visions, like which KEEP are being investigated, what are the teams working on, the vision for several years forward, and some KEEP updating. We just want to dream!
Another thing is that as a Kotlin/JVM user, I sometimes feel like a second-class citizen. I understand that some push must be needed for Native and JS, but does that really mean for instance that we still can’t have invokedynamic instructions, which is a performance killer which seems fairly easy to fix (KT-26060)? Why is the default JVM compatibility 1.6… I mean 1.8 is EOL now, and even Android phones have had full 1.8 compatibility for years, so it can’t be used anymore as an excuse? Why do users of Java library have to push several years to make many of them work with Kotlin, when so much is communicated on it’s Java interoperability (like KT-4779)? Why do you really don’t want us to use sun.* internal classes, even though there are some real uses cases, and we are perfectly entitled to use them when we deploy our own JRE with our application? Why do I increasingly have to code hack Java classes to workaround similar cases, while having the impression of missing out on more and more good stuff from Java? Argl, where is my Bromazepam pill?
Valhalla? Communicated? Really? I’ve been in Java development for about ten years, all ten years we are waiting for Valhalla, and there are no indication that it will be finished in another five years. The same goes for Panama. Loom shows some promise of being released in our lifetime, but coroutines are already in kotlin and it took only few years. As for JDK fatures, there are almost non since JDK 11 and none are planned. Some minor language features for java, but nothing compared to kotlin yet.
I do not really understand complaints about slow pace. Yeah, 1.4 does not bring a lot of new things, but look at 1.2 and 1.3. Only in two years we got tremendous progress both in language and tooling. I personally really want KEEP-176 and some performance optimizations like https://youtrack.jetbrains.com/issue/KT-29460, but I still think that the good basement and compiler stability is much more important.
There’s a problem here. Language development is not packing features over features. Kotlin is arguably already very rich, I really hope it won’t end as C#, with basically everything thrown inside the language, making it complicated, and making it difficult for people to understand what another programmer wrote.
Java won’t ever “catch up” with Kotlin for a simple reason: legacy. Java needs to guarantee that (most of) valid Java 5 and previous code still is valid code for Java 14 and future. This imposes several limits on how the language can be improved.
I believe Kotlin should focus on strengthening the toolchain (Dokka does not work well with Java 11, for instance) and multiplatform support. Make what’s there work as solidly as possible.
Language-wise, there are a number of small enhancements that I believe are way more urgent than new language features.