I use kotlin at work every day and I'm suprised it (and particular Kotlin/Compose Multiplatform) are not more popular. It's a true alternative to javascript that lets you share native ui code across web,ios,android,desktop and more (eg. watchOS).
I know this is a bit nitpicky but - if you have to compile Kotlin into a WASD binary, then use JavaScript to load it, is that really ‘native?’
You can just run JavaScript right out of the url field or the console in the browser, no compilation or server required - that’s what I would think of as ‘native.’
all the cross-platform alternatives are either very low level (C++) or Javascript, so I'm guessing they actually meant Javascript (Electron, React Native, etc)?
To me, it feels like Kotlin for the backend isn't really all that popular in the US from what I read on HN, but here in Europe there are a lot of companies (big and small) using it. Maybe it's the geographic proximity (JetBrains being a Czech company).
I am not sure if it has something to do with age. But I found both Kotlin and Swift share pretty much the same thing. Over Complexity. Objective C and Java works.
I am also wondering if Meta still uses PHP or Hack.
> I am also wondering if Meta still uses PHP or Hack
Meta’s WWW codebase is its oldest, and still written in Hacklang. Lots of internal tooling is also written in Hack.
I wouldn’t be surprised if there are more committed lines of Hacklang than any other language (although, a good chunk of that is codegen, vs other core languages where codegen is part of the build process).
Even otherwise, at the scale the company operates it's much better to run codegen once at commit time rather than recreate the entire codebase on every deploy (several times a day) which would take forever.
Additionally, the above-linked JEP only proposes to make a small subset of types potentially null-safe. The goal there is performance, not correctness.
It will eventually be a goal. Java does things in steps. First will be introducing the syntax, then another JEP will take care of the standard library. Just like they introduced virtual threads and then introduced structured concurrency. Or like introducing records and then introducing pattern matching over records. Baby steps.
> I really miss Java’s exception safety in Kotlin.
Java is the only language that I'm aware of with checked exceptions (Swift has "throws" which I guess goes in that direction but is untyped) and it's in my experience not notably exception-safer than languages that use values for error handling (such as Rust, Haskell or Kotlin).
Swallowing exceptions because of bad ergonomics or misuse by library authors is unfortunately fairly common in a lot of Java code that I've seen. By contrast, most Kotlin code that I've seen uses exceptions only for unrecoverable errors and otherwise uses some sort of sum type (Result, Either or some sealed class/interface). These can be handled ergonomically and in a very type-safe manner - and importantly they don't break when used with higher-order functions. In the future, Kotlin will have Rich Errors which will have even better ergonomics (I'm personally fine with Either, but I know some people dislike a heavily functional style, so this will be good for them).
> Swallowing exceptions because of bad ergonomics or misuse by library authors is unfortunately fairly common in a lot of Java code that I've seen
This is because the language has not invested to make the ergonomics better. Checked exceptions/errors are still superior than runtime exceptions. "Misuse" can still occur with values. Bad developers can still bubble errors they can't handle and that you can't handle either. I've written elsewhere [0] the things that Java needs.
> By contrast, most Kotlin code that I've seen uses exceptions only for unrecoverable errors
Except for the whole Kotlin standard library. Like you said the errors as unions proposal is very far away. So either I need to adopt some library and then when unions come I now have 2-3 competing systems + whatever the libraries are using. I'd rather just use checked exceptions.
> - and importantly they don't break when used with higher-order functions.
This is not a property of values or exceptions. It's a property of the type system. Checked exceptions can work perfectly fine with higher order functions, Scala has done good research there [1] and I believe Swift's typed throws works with lambdas as well; Java just hasn't invested in the language.
Ultimately, there is no difference because Result<T, Error> and T func() throws Exception. One is not superior to the other. What it comes down to for me is whether a language has support for checked errors or not, and Kotlin does not.
Checked errors are not categorically better than runtime exceptions. There are lots of things that should never be checked exceptions: division by zero, illegal array access, OOM, and everything that can't be (at least not locally) recovered from.
I'm not sure what you mean. Most kotlin stdlib functions that can fail have some sort of "...orNull" variant to be used when you're not sure you're going to get something back, and there's "runCatching" which will wrap any exceptions in a Result type.
Result is part of the stdlib, so you don't have to use any library, although some people (me included) prefer Either. If/when they introduce Rich Errors, it's going to be semantically almost equivalent to Either, except you get somewhat improved ergonomics, so it's not really a paradigm shift.
> Ultimately, there is no difference because Result<T, Error> and T func() throws Exception. One is not superior to the other. What it comes down to for me is whether a language has support for checked errors or not, and Kotlin does not.
I don't understand how those two sentences don't contradict each other. Kotlin has support for Result<T> (stdlib) or Either<E, T> (from libraries like Arrow). Since you're agreeing that this is equivalent to checked exceptions I don't understand how you can claim that Kotlin doesn't support checked errors. It supports them just as well as Java does, it just has a different philosophy around it. (I guess the one point that I'll concede is that it can cause issues when interfacing with Java code and it would be nice if Kotlin had some better ergonomics around automatically inferring errors from Java library code the way it does for nullability checks; but in practice this hasn't been a big issue for me).
FWIW, I disagree that there isn't a big distinction. If the exception is part of the regular type, it is a value and it can be manipulated like any other value, making it very easy to write all sorts of code that manipulates exceptions. Of course, you could eventually write enough machinery so that you get the same power also with checked exceptions, but that just makes the language more complicated for questionable gain. And in any case, Java doesn't do that.
The Scala discussion you're linking is certainly interesting, but it's cutting-edge PL research (effect systems). I'm not sure how this matters in a discussion of tradeoffs between Java and Kotlin today.
I never worked with Kotlin, but have kept it in the back of my head as the simpler alternative to Java if I had to target the JVM. What makes it more complex?
Disclaimer. Last time I seriously used Java, I was using Java 8, and I've only used Kotlin for screwing around with Android development on my own time. So what follows might be way off.
Kotlin provides a lot of 'clever' syntactic sugar and features that makes certain things that are quite verbose in Java, nice and compact in Kotlin. It also means that there are many way to achieve the same thing in Kotlin. Once you've learned everything it allows you to do things that would take a lot of Java in much fewer lines of code. But there is also just more 'stuff' to learn in the Kotlin language.
Java is a much simpler language than Kotlin with relatively few features, but this simplicity means you sometimes have to build quite verbose structures to achieve what you want.
So which is 'simpler' very much comes down to how you define 'simple'.
Java also has to maintain backwards compatibility at (almost) all cost, so it has a lot of warts that it can't or won't remove. For example, I think there are like 4 or 5 different types of switch statements/expressions.
I also think that checked exceptions are a major flaw (particularly because they don't work well with lambdas) but I don't foresee them getting removed anytime soon.
Oh I see, so this is kind of like with Ruby, where people build a lot of magic that looks simple but hides complexity that you still need to understand.
No. Unlike Ruby, Kotlin is compiled and you can't monkeypatch things, so unless you go out of your way to do reflection magic (something that is unfortunately common in the Java community), you won't get weird runtime surprises like not knowing where a method comes from.
I'd say the magic of Kotlin comes down to a few syntactic constructs that compose very well. Also, a decent type system helps with understanding any magic, even those not tastefully created.
Since then, Java has incorporated a lot of the syntactic sugar from Kotlin. Not all of it; they're still very judicious about trying to keep the language tight. But things like the lambda features have even made it down into the JVM (which is actually incredibly stable).
Kotlin's one big advantage is having avoided the "billion dollar mistake" of null pointers. Or at least, mitigated it. But in my opinion it's not sufficient to install a whole new language into your stack.
I use kotlin at work every day and I'm suprised it (and particular Kotlin/Compose Multiplatform) are not more popular. It's a true alternative to javascript that lets you share native ui code across web,ios,android,desktop and more (eg. watchOS).
I know this is a bit nitpicky but - if you have to compile Kotlin into a WASD binary, then use JavaScript to load it, is that really ‘native?’
You can just run JavaScript right out of the url field or the console in the browser, no compilation or server required - that’s what I would think of as ‘native.’
Do you mean a 'Java' alternative?
all the cross-platform alternatives are either very low level (C++) or Javascript, so I'm guessing they actually meant Javascript (Electron, React Native, etc)?
To me, it feels like Kotlin for the backend isn't really all that popular in the US from what I read on HN, but here in Europe there are a lot of companies (big and small) using it. Maybe it's the geographic proximity (JetBrains being a Czech company).
I am not sure if it has something to do with age. But I found both Kotlin and Swift share pretty much the same thing. Over Complexity. Objective C and Java works.
I am also wondering if Meta still uses PHP or Hack.
> I am also wondering if Meta still uses PHP or Hack
Meta’s WWW codebase is its oldest, and still written in Hacklang. Lots of internal tooling is also written in Hack.
I wouldn’t be surprised if there are more committed lines of Hacklang than any other language (although, a good chunk of that is codegen, vs other core languages where codegen is part of the build process).
Why don't they do codegen at build time in Hack?
Hack does JIT compilation.
Even otherwise, at the scale the company operates it's much better to run codegen once at commit time rather than recreate the entire codebase on every deploy (several times a day) which would take forever.
Why don't they do the same in other languages, then?
I really miss Kotlin's null safety in Java
I really miss Java’s exception safety in Kotlin.
If Java ever ships Valhalla we might get null restricted types: https://openjdk.org/jeps/8316779
Note that you can get null safety in Java today from third-party static analysis tools: https://jspecify.dev/docs/whether/#nullness-checker-support-...
Additionally, the above-linked JEP only proposes to make a small subset of types potentially null-safe. The goal there is performance, not correctness.
I linked the wrong JEP because I was tired. The goal is correctness: https://openjdk.org/jeps/8303099
> Enhance Java's reference types to let programmers express whether null references are expected as values of the type
> It is not a goal (at this time) to apply the language enhancements to the standard libraries
That seems really very limiting and like it would make the feature not very useful in practice.
> (at this time)
It will eventually be a goal. Java does things in steps. First will be introducing the syntax, then another JEP will take care of the standard library. Just like they introduced virtual threads and then introduced structured concurrency. Or like introducing records and then introducing pattern matching over records. Baby steps.
> I really miss Java’s exception safety in Kotlin.
Java is the only language that I'm aware of with checked exceptions (Swift has "throws" which I guess goes in that direction but is untyped) and it's in my experience not notably exception-safer than languages that use values for error handling (such as Rust, Haskell or Kotlin).
Swallowing exceptions because of bad ergonomics or misuse by library authors is unfortunately fairly common in a lot of Java code that I've seen. By contrast, most Kotlin code that I've seen uses exceptions only for unrecoverable errors and otherwise uses some sort of sum type (Result, Either or some sealed class/interface). These can be handled ergonomically and in a very type-safe manner - and importantly they don't break when used with higher-order functions. In the future, Kotlin will have Rich Errors which will have even better ergonomics (I'm personally fine with Either, but I know some people dislike a heavily functional style, so this will be good for them).
Swift has typed throws now.
> Swallowing exceptions because of bad ergonomics or misuse by library authors is unfortunately fairly common in a lot of Java code that I've seen
This is because the language has not invested to make the ergonomics better. Checked exceptions/errors are still superior than runtime exceptions. "Misuse" can still occur with values. Bad developers can still bubble errors they can't handle and that you can't handle either. I've written elsewhere [0] the things that Java needs.
> By contrast, most Kotlin code that I've seen uses exceptions only for unrecoverable errors
Except for the whole Kotlin standard library. Like you said the errors as unions proposal is very far away. So either I need to adopt some library and then when unions come I now have 2-3 competing systems + whatever the libraries are using. I'd rather just use checked exceptions.
> - and importantly they don't break when used with higher-order functions.
This is not a property of values or exceptions. It's a property of the type system. Checked exceptions can work perfectly fine with higher order functions, Scala has done good research there [1] and I believe Swift's typed throws works with lambdas as well; Java just hasn't invested in the language.
Ultimately, there is no difference because Result<T, Error> and T func() throws Exception. One is not superior to the other. What it comes down to for me is whether a language has support for checked errors or not, and Kotlin does not.
[0] https://news.ycombinator.com/item?id=44432640
[1] https://docs.scala-lang.org/scala3/reference/experimental/ca...
Checked errors are not categorically better than runtime exceptions. There are lots of things that should never be checked exceptions: division by zero, illegal array access, OOM, and everything that can't be (at least not locally) recovered from.
That's why Kotlin's philosophy is and has for a long time been "use values for expected and recoverable errors, runtime exceptions for unexpected and unrecoverable conditions", see: https://elizarov.medium.com/kotlin-and-exceptions-8062f589d0...
> Except for the whole Kotlin standard library.
I'm not sure what you mean. Most kotlin stdlib functions that can fail have some sort of "...orNull" variant to be used when you're not sure you're going to get something back, and there's "runCatching" which will wrap any exceptions in a Result type.
Result is part of the stdlib, so you don't have to use any library, although some people (me included) prefer Either. If/when they introduce Rich Errors, it's going to be semantically almost equivalent to Either, except you get somewhat improved ergonomics, so it's not really a paradigm shift.
> Ultimately, there is no difference because Result<T, Error> and T func() throws Exception. One is not superior to the other. What it comes down to for me is whether a language has support for checked errors or not, and Kotlin does not.
I don't understand how those two sentences don't contradict each other. Kotlin has support for Result<T> (stdlib) or Either<E, T> (from libraries like Arrow). Since you're agreeing that this is equivalent to checked exceptions I don't understand how you can claim that Kotlin doesn't support checked errors. It supports them just as well as Java does, it just has a different philosophy around it. (I guess the one point that I'll concede is that it can cause issues when interfacing with Java code and it would be nice if Kotlin had some better ergonomics around automatically inferring errors from Java library code the way it does for nullability checks; but in practice this hasn't been a big issue for me).
FWIW, I disagree that there isn't a big distinction. If the exception is part of the regular type, it is a value and it can be manipulated like any other value, making it very easy to write all sorts of code that manipulates exceptions. Of course, you could eventually write enough machinery so that you get the same power also with checked exceptions, but that just makes the language more complicated for questionable gain. And in any case, Java doesn't do that.
The Scala discussion you're linking is certainly interesting, but it's cutting-edge PL research (effect systems). I'm not sure how this matters in a discussion of tradeoffs between Java and Kotlin today.
I don't really have the energy to debate this, but the Kotlin standard library doesn't use Result at all:
It does however throw a shit ton of exceptions: So like I said the language doesn't tell you what can error. Cheers man.I prefer Scala's Option over Kotlin's nulls.
I never worked with Kotlin, but have kept it in the back of my head as the simpler alternative to Java if I had to target the JVM. What makes it more complex?
Disclaimer. Last time I seriously used Java, I was using Java 8, and I've only used Kotlin for screwing around with Android development on my own time. So what follows might be way off.
Kotlin provides a lot of 'clever' syntactic sugar and features that makes certain things that are quite verbose in Java, nice and compact in Kotlin. It also means that there are many way to achieve the same thing in Kotlin. Once you've learned everything it allows you to do things that would take a lot of Java in much fewer lines of code. But there is also just more 'stuff' to learn in the Kotlin language.
Java is a much simpler language than Kotlin with relatively few features, but this simplicity means you sometimes have to build quite verbose structures to achieve what you want.
So which is 'simpler' very much comes down to how you define 'simple'.
Java also has to maintain backwards compatibility at (almost) all cost, so it has a lot of warts that it can't or won't remove. For example, I think there are like 4 or 5 different types of switch statements/expressions.
I also think that checked exceptions are a major flaw (particularly because they don't work well with lambdas) but I don't foresee them getting removed anytime soon.
Oh I see, so this is kind of like with Ruby, where people build a lot of magic that looks simple but hides complexity that you still need to understand.
No. Unlike Ruby, Kotlin is compiled and you can't monkeypatch things, so unless you go out of your way to do reflection magic (something that is unfortunately common in the Java community), you won't get weird runtime surprises like not knowing where a method comes from.
I'd say the magic of Kotlin comes down to a few syntactic constructs that compose very well. Also, a decent type system helps with understanding any magic, even those not tastefully created.
Since then, Java has incorporated a lot of the syntactic sugar from Kotlin. Not all of it; they're still very judicious about trying to keep the language tight. But things like the lambda features have even made it down into the JVM (which is actually incredibly stable).
Kotlin's one big advantage is having avoided the "billion dollar mistake" of null pointers. Or at least, mitigated it. But in my opinion it's not sufficient to install a whole new language into your stack.
One day we’ll get nullable types: https://openjdk.org/jeps/8303099
I believe I read on the mailing list it’s implemented here: https://github.com/openjdk/valhalla/tree/lw5
IME, it's sort of like the difference between C and C#.
Kotlin is incredibly expressive and can get quite complicated. Java is a bit more brutally simple (and obviously more verbose).
As a C# dev primarily, I love Kotlin, and I've always hated Java despite it being the very first language I learned.
I wouldn't call Kotlin simple by any stretch of the imagination. It's just a very high-level language.
Coming from Scala and TypeScript, I always thought Kotlin had under complexity.
Kotlin is awesome, good on Meta.