I was waiting for this comment. Every single thread about Scala has someone pushing this narrative that Kotlin is the real arbiter of change when it really has been Scala the entire time pushing boundaries on the JVM.
Kotlin is great and if you want a cleaner Java experience, by all means use it but Scala is real champion in pushing many, many things into the mainstream.
Java has not picked up a single feature from Kotlin yet (maybe nullability types someday?), and, in fact, opted for very different ones (e.g. contrast records vs. data classes, virtual threads vs. syntactic couroutines), although I guess Scala has provided some inspiration for some features, as Java's are closer to Scala's than to Kotlin's. ML is probably the biggest influence, with some Haskell flavour. But I find it amusing that people think that Java is trying to compete with other languages on the Java platform, no matter how small, rather than with bigger, more relevant competitors.
Java records and sealed types are its interpretation of product and sum types, and, true, this interpretation draws inspiration from Scala's. Deconstructing patterns are coming soon, but Java now does have real syntax for ADTs:
sealed interface Expr {}
record ConstantExpr(int i) implements Expr {}
record PlusExpr(Expr a, Expr b) implements Expr {}
record TimesExpr(Expr a, Expr b) implements Expr {}
record NegExpr(Expr e) implements Expr {}
For non-record classes, deconstructing patterns will be something like a dual to methods, and almost a first-class citizen. Among other things, they will allow patterns to support API designs that predate records and sealed types.
Ok, it's perhaps a true Scotsman argument but saying that Java as a syntax for ADT is like saying JS (pre 2015) has classes because it can be simulated by function + prototype or that Java (pre 8) has lambdas because it can be simulated by anonymous classes.
Java misses the syntactic sugar to define ADT in one place like in Standard ML, OCaml or F#.
The closest you get is to declare records inside a sealed interface, but once you add generics in the mix, it starts to get messy.
I was not able to define a classical list with cons and nil in Java.
sealed interface List<T> {
record Cons<T>(T car, List<T> cdr) implements List<T> {}
record Nil() implements List {}
}
The compiler give you warnings, Cons<T> or Nil are not a top level type and you can create several instances of Nil.
Pattern matching will work fine with an additional explicit nil() pattern. I agree that in this particular case it's not quite as succinct as in more functional languages, but virtually all cases in ordinary business applications are not like that, and the additional code, if any, is O(1).
Of course, Java could add rules for the special case of zero-argument records, making them more enum-like, but I really think the value in doing that is negative. Other than being able to directly translate ML examples, it would add complexity that isn't worth it.
In fact, in this particular case I'd do it like so:
record List<T>(T car, List<? extends T> cdr) {
public List { if (car == null) throw new IllegalArgumentException("null element"); }
}
Which would give you:
switch(list) {
case List<String>(var car, var cdr) -> ...
case null -> ...
}
It might not be exactly what people who like Scala might prefer, but it is very much a good representation of ADTs for those who prefer Java.
What are you talking about? Java release notes look like a list of Kotlin features these days.
Sealed classes, data classes, multiline strings, coroutines -> project loom, switch statement improvements to resemble Kotlin when statement, improvements to Streams to match Sequences.
You do realize there are plenty of languages out there, and most novel features appeared first in some minor research languages? Like, there is hardly anything original to kotlin on your list, sealed classes have been in scala forever, and are basically just algebraic data types. Data classes are.. data classes, multiline strings is a cool but very basic syntactic sugar available in millions of languages, coroutines have been around, and kotlin’s couroutines are nothing like project loom. The latter is more similar to go’s threads. Switch expressions have been in scala forever, but a pretty basic thing in FP languages.
That’s irrelevant. It’s not like the language team didn’t know about these features. The change to the shorter release cycle and increased funding is much more behind the speed up of updates regarding Java.
You keep claiming that the language team's knowledge of a feature drives that feature's adoption.
That's not accurate.
Popularity of a feature and enterprise demand drive it's adoption.
It doesn't really matter what the language team knows, it matters what the average developer knows since their collective wants are in large part what drives the language team.
There are hundreds of thousands of Java devs who only ever wrote Java and suddenly had to write Kotlin, and are now clambering for these feature improvements in Java.
1. That's not really right. You're correct that "readiness" is important, but Python and JS are much bigger forces than Kotlin, and the main reason Java is getting features faster is because the investment in the platform has grown (and Kotlin was created when it was at an ebb). But so far, almost all linguistic features added after 1.0 -- generics, lambdas, type inference, ADTs, patterns -- are inspired by ML.
2. Java addresses those topics (where relevant) pretty much in the opposite way from Kotlin. Java rejected coroutines and is going down a completely different path with virtual threads; Java rejected data classes and chose to go down algebraic data types. So if you think Java gets inspiration from Kotlin, then it is in the form of what not to do.
I would agree with you, Java routinely uses the "last-mover's advantage" tactic, but I think you overestimate the relative sizes of the two languages. These are all very basic FP "features"/language primitives, and Java is steering strongly towards becoming an ML-inspired FP-enhanced language.
If anything, the acceptance of more parts of the FP paradigm into all major languages (like C#, JS/TS, C++) starting with lambdas likely have pushed Java, but to single out the all-around very niche Kotlin language as a source is imo a non sequitur.
These aren’t ‘Kotlin features’ they’re just normal language features.
I really struggle to see Kotlin as being part of the debate here. These features are being driven by enterprise Java user pain points. And those people aren’t looking at Kotlin.
I agree that this would probably happen in the Java world, regardless of kotlin. However, I disagree with the statement that enterprise Java users are not looking at kotlin. From my view (in a large, global consulting business), we see large enterprise Java users adopting kotlin.
>These features are being driven by enterprise Java user pain points
By Java devs who only ever wrote Java, and suddenly had to write Kotlin for Android. They're now aware of these features as a result and are demanding them in Java.
Scala was probably the major factor here. However, the fact that Kotlin picked up these features from Scala (or at least inspired it) also proves that they are mature/stable and this has always been important for Java - so Kotlin did have an impact as well.
It doesn't matter "who did the trick". It is well known that Java was influenced by ideas in other programming languages from the beginning. And also other languages - including Scala and Kotlin - are similar in this respect... So yes: Kotlin influenced Java and Java influenced Kotlin. Let's compare final products with final products and not "how did we get there"...
Kotlin doesn't sound like a good language to bet on since most suitable(for jvm) features it has will be integrated by Java now that it has picked up pace.
I guess it only has decent marketshare because of google's android support(they are throwing stuff on the wall to move away from Oracle IP i guess) and Jetbrains being very popular among java devs.
That story regarding Kotlin and Oracle doesn't sell because unless Google rewrites Android toolchains in Kotlin/Native, there is plenty of JVM infrastructure to deal with, and so far there haven't been signs to fully replace Android Java.
The sour grapes of the Kotlin/Android marriage is that going forward one will need KMM for code between JVM and ART, or be happy to just use what ART undestands.
I don't know about betting on it, but the type before identifier syntax has always been a pet peeve of mine, and so I'd never willingly use java if I have a choice. And null handling. Fuck Java's ridiculously verbose and error prone null handling.
I'll be sticking with Kotlin at least until Java can do better at killing null pointers than @NotNull. Optional is good, but not widely used enough to handle most cases.
I was recently evaluating Kotlin vs Java for a new Android app. Two factors made me choose to bet on Kotlin.
1) Jetpack Compose is very loudly Kotlin-first
2) I did a survey of Android developer job postings. Literally ALL of them were for Kotlin, with Java mentioned as a nice-to-have roughly 50% of the time.
On a technical note, I don't see Java fixing NPEs, checked exceptions, or general verbosity any time soon. Java gets to live with its legacy of bad choices, Kotlin is able to stay clean while still providing backward support by integrating with old Java code .
One either gets to say where the platform goes, or keeps playing catch-up with its features, requires additional tooling, wrapper libraries, care about FFI, IDE plugins that understand all of that in a coherent way.
What they probably meant is that both Scala's and Kotlin's improvements pushed Java to improve. Both languages had many different features that back then weren't available in Java but since then got added to the Java language, and that made Java better, too.
I still don't see how Kotlin is involved. People drafting JEPs are well aware of how modern languages, including the ones running on the JVM, have evolved in the past decades. Kotlin is pretty late to the party and hasn't really brought anything new to the JVM (by choice), except for coroutines maybe.
And they were in Scala, Groovy, C# ... before Kotlin was even a thing. There's zero evidence people on the OpenJDK governing board care about Android at all, rather the opposite.
Except Scala brought along some improvements and a whole managerie of other features to manage, Groovy with its gradual typing was simultaneously too far away from Java and yet too similar, and C# means opting into a whole different platform and perpetually living downstream of whatever MS wants to do.
Kotlin absolutely nailed the "meaningfully better than Java while staying pedantically true to the existing semantics" in a way that none of the alternatives did even if they did come first.
Here's a quote from Reynolds, one of the creators of Spark:
> The primary issue I can think of comes from the lack of pattern matching. Kotlin’s language designer left out pattern matching intentionally because it is a complex feature whose use case is primarily for building compilers. However, modern Spark (post Catalyst / Tungsten) look a lot like compilers and as a result the internals would become more verbose if built using a language that doesn't support pattern matching.