Live data from Hacker News

Kotlin's rich errors: Native, typed errors without exceptions

cekrem.github.io

61–70 of 84 posts

Re: Kotlin's rich errors: Native, typed errors without exceptions

#61
post #14

Rich Errors look promising to me, but what about interop with Java? What will the return-type of a function be on the Java side be, if the return type on Kotlin side is: Int | ParseError | SomeOtherError? Background: unions aren't restricted to one normal type and one error type, but to one normal type and any number of error types, so this can't be modelled as syntactic sugar on top of an implicit Either/Result type…

They only care about Java -> Kotlin integration. Not the other way around. It has been like this for a long time. Looks like an extractive relationship to me to be frank.

Kotlin does have interop with Java, but is limited by either the features not existing in Java (non-nullable types) or behave differently in Java (records, etc.).

You have to explicitly annotate that a Kotlin data class is a Java record due to the limitations Java has on records compared to data classes [1]. This is similar to adding nullable/not-null annotations in Java that are mapped to Kotlin's nullable/non-nullable types.

Where there is a clean 1-1 mapping and you are targeting the appropriate version of Java, the Kotlin compiler will emit the appropriate Java bytecode.

[1] https://kotlinlang.org/docs/jvm-records.html#declare-records...

Re: Kotlin's rich errors: Native, typed errors without exceptions

#62

Does anyone know of a great write up on exceptions vs union or either typed returns? I'm building a new language, somewhat similar to TypeScript in some ways, and so far I have exceptions and try/catch expressions, but also Optional and Result types. I'm familiar and used to exceptions, so I included them so at least near-fatal errors (ie, actually exceptional) could be caught at high levels in the stack. But I'm uns…

Both Rust and Go are good examples of modern languages with no exceptions.

Not coincidentally, both provide a panic mechanism, which is intended for failures that are either unrecoverable or at least not locally recoverable. Both languages allow you to "catch" panics, but this mechanism is constrained and impractical to use for normal error handling. Instead, it's used to e.g. prevent a service from crashing if individual requests fail unrecoverably.

The point is that these languages both demonstrate a simple design for exception-free languages.

(Although Rust's approach is better in several ways, partly because it has a better type system.)

Re: Kotlin's rich errors: Native, typed errors without exceptions

#63
post #58

These remind me of checked exceptions in Java. Ironically, Kotlin removed checked exceptions because they tend to be annoying more than useful: there's no clear guideline to whether an exception is checked or unchecked, some functions like IO and reflection have them while others don't, they're verbose especially when closures are involved, and lots of functions simply catch and rethrow checked exceptions in unchecke…

Because Kotlin took a dumb turn about 5 years ago and decided that multiplatform was their future instead of the jvm (because they felt threatened by React Native and Flutter on Android). Point being, they don't want to tie themselves to the jvm anymore. The language has been stagnant for years as they've had to reimplement tons of java libraries and also shoehorn the extreme complications of multiplatform into the a…

Thank god they did, they are in a really good place now

Re: Kotlin's rich errors: Native, typed errors without exceptions

#64
post #57

The innovation here is, I think, the use of union types. The problem with errors as standard algebraic data types (ADTs) is you end up with lots of boilerplate to transform from one ADT to another, as errors propagate through the system. With union types (as found in Typescript and Scala 3) you can add and remove types from the union in an ad-hoc manner. IIRC Elm doesn't have union types, so I think the blog post is…

Of course Elm has union types, it’s like one of its main features! https://guide.elm-lang.org/types/custom_types.html

I mean union types in the programming language theory sense, not in the "we called this language feature union types" sense. Elm's union types are algebraic data types (ADTs). Union types in the PLT sense are what Typescript has. The main difference is that an ADT must be declared upfront, whilst a union type can be constructed in an ad-hoc manner based on whatever types are used together at a particular point in the program.

Re: Kotlin's rich errors: Native, typed errors without exceptions

#65
post #58

These remind me of checked exceptions in Java. Ironically, Kotlin removed checked exceptions because they tend to be annoying more than useful: there's no clear guideline to whether an exception is checked or unchecked, some functions like IO and reflection have them while others don't, they're verbose especially when closures are involved, and lots of functions simply catch and rethrow checked exceptions in unchecke…

Because Kotlin took a dumb turn about 5 years ago and decided that multiplatform was their future instead of the jvm (because they felt threatened by React Native and Flutter on Android). Point being, they don't want to tie themselves to the jvm anymore. The language has been stagnant for years as they've had to reimplement tons of java libraries and also shoehorn the extreme complications of multiplatform into the a…

> Because Kotlin took a dumb turn about 5 years ago and decided that multiplatform was their future instead of the jvm (because they felt threatened by React Native and Flutter on Android).

It’s because JB intends to make money on their investment, unlike the other two. This is the reason why Kotlin ecosystem is a half baked mess – JB tries to artificially replicate all successful ecosystems without having a community.

Re: Kotlin's rich errors: Native, typed errors without exceptions

#66
post #50

Earlier quoted context omitted.

> But I do remember when Kotlin broke on to the scene in 2015, and most of us were thrilled to finally move beyond Java 7! n=1 but i was there with android studio v0.01 (or thereabouts) using kotlin for a production app cause i was so sick of old-java + eclipse... google was asleep at the wheele imo and android development would be nowhere near where it is today without jetbrains

Compared to Apple and Microsoft, Android development is mostly outsourced. None of the development environments is from Google, none of the languages as well, or the build tools for app developers (Internally they use Bazel and Soong). Naturally having gone into bed with JetBrains for the IDE, after leaving NDK users without IDE tooling for almost two years during the IDE transition, the deal was in place to push Kot…

> I am surprised Google hasn't yet bought JetBrains.

Why would they? It’s the best of both worlds. They can pay a fraction of the price while having 100% of the benefits.

Re: Kotlin's rich errors: Native, typed errors without exceptions

#67

These remind me of checked exceptions in Java. Ironically, Kotlin removed checked exceptions because they tend to be annoying more than useful: there's no clear guideline to whether an exception is checked or unchecked, some functions like IO and reflection have them while others don't, they're verbose especially when closures are involved, and lots of functions simply catch and rethrow checked exceptions in unchecke…

Exceptions are cheap on the happy path and super expensive on the error path. Checked exceptions only make sense for errors that are relatively common (i.e., they aren't really exceptional), which calls for a different implementation entirely where both the happy path and the error path have around the same cost. This is what modern languages like Rust and Go do as well (and I think Swift as well though don't quote m…

Result or Error types may just be normal values, but they add overhead to the code as well when they’re ubiquitous.

Once they’re the standard error method then case every function has to intertwine branching for errors paths vs normal paths. Often the compiler has to generate unique code or functions to handle each instance of the Result type. Both add to code size and branching size, etc.

Re: Kotlin's rich errors: Native, typed errors without exceptions

#68
post #53

Earlier quoted context omitted.

That Midori article looks great, I'll give that a closer read. I actually used to work with Bob, and am familiar with the (wonderful!) function color article. I think my biggest question might be addressed in the Midori article: with things like bounds checks and checked casts you already have exceptions (or panics), so should you have a way to capture them anywhere on the stack? Are they recoverable in some programs…

Pretty much every language has a form of resumable exception known as a "function call". It's hard for me to understand why no one in the algebraic effects/effect handlers community has noticed this yet.

This is the difference between functions and effect handlers, to my understanding:

Functions map inputs to outputs, with a type signature that looks like A -> B. Functions may be composed, so if you have f: A -> B and g: B -> C, you have gf: A -> C. Function composition corresponds with how "ordinary" programming is done by nesting expressions, like g(f(x)).

Sometimes, the function returns something like Option or Future. "Ordinary" function composition would expect the subsequent function's input type to be Future, but frequently you need that input to have type B. Therefore, optionals or futures require "Kleisli composition," where given f: A -> Future and g: B -> Future, you have gf: A -> Future. Kleisli composition corresponds with "monadic" programming, with "callback hell" or some syntactic sugar for it, like:

    let y = await f(x);
    g(y)
Effect handlers allow you to express the latter, "monadic" code, in the former, "direct style" of ordinary function calls.

Re: Kotlin's rich errors: Native, typed errors without exceptions

#69
post #4

Rich Errors look promising to me, but what about interop with Java? What will the return-type of a function be on the Java side be, if the return type on Kotlin side is: Int | ParseError | SomeOtherError? Background: unions aren't restricted to one normal type and one error type, but to one normal type and any number of error types, so this can't be modelled as syntactic sugar on top of an implicit Either/Result type…

> what about interop with Java? From the proposal discussion[0], the runtime representation on the JVM will just be `Object`. [0]: https://github.com/Kotlin/KEEP/discussions/447#discussioncom...

Oof. That's pretty gross: just throw away all typesafety?

A `Result` return type is way better.

This feels like it'll be viewed like Java's `Date` class: a mistake to be avoided.

Re: Kotlin's rich errors: Native, typed errors without exceptions

#70
post #58

Earlier quoted context omitted.

Because Kotlin took a dumb turn about 5 years ago and decided that multiplatform was their future instead of the jvm (because they felt threatened by React Native and Flutter on Android). Point being, they don't want to tie themselves to the jvm anymore. The language has been stagnant for years as they've had to reimplement tons of java libraries and also shoehorn the extreme complications of multiplatform into the a…

> Because Kotlin took a dumb turn about 5 years ago and decided that multiplatform was their future instead of the jvm (because they felt threatened by React Native and Flutter on Android). It’s because JB intends to make money on their investment, unlike the other two. This is the reason why Kotlin ecosystem is a half baked mess – JB tries to artificially replicate all successful ecosystems without having a communit…

How so? The Android ecosystem literally became the Kotlin ecosystem it was so successful. The multiplatform stuff came out of organic demand for re-using code at first between JVM backend and browser (Kotlin/JS), and then for re-using code between JVM, JS, Android and sharing the business logic on iOS, and then finally for being able to reuse UI code on iOS too for cases where native Swift UI can't be justified (obscure apps, etc).

Seems to me like Kotlin Multiplatform has been quite successful actually. The weakest part is Kotlin/Native where they could have just used GraalVM Native Image but I talked to the Kotlin team about that at the time and it was more of an opportunistic move than anything else - a compiler team in St Petersburg had been let go by Intel and JB could acquire the whole team cheaply.

Post reply on HN