News for hackers. Stuff that matters.
Re:JEP draft: Exception handling in switch by tadfisher on Friday April 19, 2024 @01:22PM (#40089524)
My approach lately is either:

- Ban exception propagation altogether: in Kotlin, wrap the computation in 'runCatching' to get a Result<T>; or in Java, use result4j [1] which provides similar functionality.

- Let exceptions propagate, catching them at as high a level as possible.

Which one to go with depends on the type of program I'm writing. If it's a GUI tool, I go with the first approach, because I want to display errors to the user. If it's a CLI tool or backend service, I go with the second option, because I want to short-circuit the program as soon as possible to avoid potential logic errors.

[1]: https://github.com/sviperll/result4j

Re:JEP draft: Exception handling in switch by ackfoobar on Friday April 19, 2024 @02:26PM (#40090348)
> Let exceptions propagate, catching them at as high a level as possible.

This can't be done cleanly in Java.

Checked exception can encode union types, but this extra power is not complemented anywhere else in Java's type system. E.g. in a `Consumer` lambda passed to `forEach`, Java's checked exception forces you to convert that to a RuntimeException.

Re:JEP draft: Exception handling in switch by PhilipRoman on Friday April 19, 2024 @03:25PM (#40091004)
I'd say it is due to a lack of variadic type parameters. You can write something like this:

    <T, X extends Throwable> void forEach(ThrowingConsumer<T, X> f) throws X;
But the only way to have multiple exception types without losing static type checking is to have multiple X parameters, like X1, X2, X3... (with unused parameters being set to some subtype of RuntimeException so that they do not participate in checked exception handling).

Whether or not it is worth to write this madness just to satisfy one's OCD is up to the reader.

Re:JEP draft: Exception handling in switch by ackfoobar on Friday April 19, 2024 @03:38PM (#40091133)
> it is due to a lack of variadic type parameters

To be pedantic, it is due to union types "not complemented anywhere else in Java's type system". Adding variadic type params is a way to solve this. Another way is, of course, to support union types.

> with unused parameters being set to some subtype of RuntimeException

Or the `Nothing` type (`never` in TypeScript), where `A | Nothing = A`.

Re:JEP draft: Exception handling in switch by bedobi on Friday April 19, 2024 @01:50PM (#40089908)
using RunCatching is inadvisable, it catches too much and can break lots of things in hard to detect ways

https://github.com/sksamuel/tabby/blob/0fa37638712efd6b059f2...

(though I recommend using the Arrow library, it has great types for fixing all the countless foot guns Kotlin devs insist on adding to the language and native libraries)

Re:JEP draft: Exception handling in switch by groestl on Friday April 19, 2024 @01:45PM (#40089852)
I tend to do the former only when writing executors, task queues, retry strategies, batch handlers, and the likes, otherwise rely on 2) (the UI is just another "high level")
Re:JEP draft: Exception handling in switch by cogman10 on Friday April 19, 2024 @01:46PM (#40089865)
I mostly work in the backend and yeah, the second approach is what I value the most.

Particularly because it can provide a ton of useful context (if logging is correctly setup) and doesn't end up littering the code with try/catch blocks and stuttered logging.

Re:JEP draft: Exception handling in switch by wiseowise on Friday April 19, 2024 @06:04PM (#40092427)
> - Ban exception propagation altogether: in Kotlin, wrap the computation in 'runCatching' to get a Result<T>; or in Java, use result4j [1] which provides similar functionality.

‘runCatching’ was never intended for user code. It was made for internal use in coroutines machinery and when community complained they made it public. But it is still a half-baked API that is better to avoid (catching CancellationException, doesn’t compose well in general).

The whole runCatching/billions of Result<T> copies are worse than Go’s “if err !=“.

Unless JetBrains rolls out language support for something like Rust’s Result, exceptions are superior and Kotlin community would better off embracing them instead of trying to be different for the sake of being different.

https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/sh...

Re:JEP draft: Exception handling in switch by rileymichael on Saturday April 20, 2024 @11:44AM (#40098200)
I have a hard time agreeing that exceptions (as they exist in kotlin, unchecked) are superior. There is no way to communicate (outside of docs) to callers that a function is possibly unsafe and that they should handle it.

Good callout on the stdlib `Result`, a lot of people aren't aware of the `CancellationException` issue. Another pain point is that the error is constrained to `Throwable`, which is rather obtuse for general business logic (and you're likely generating stack traces needlessly unless you disable `writableStackTrace` on your custom throwables).

I'm a fan of https://github.com/michaelbull/kotlin-result which has a fantastic API and supports monad comprehension which helps avoid the "arrowheads" from not having a built in operator.

Re:JEP draft: Exception handling in switch by vips7L on Saturday April 20, 2024 @03:20PM (#40100183)
That result library doesn’t look thread safe at all. I would be extremely cautious using it.
Re:JEP draft: Exception handling in switch by michaelbull on Saturday April 20, 2024 @03:27PM (#40100240)
Author here. I have no idea what you could possibly mean with this comment. The coroutineBinding implementation correctly uses the coroutines API for parallel decomposition of Result bindings, exactly how the Kotlin Coroutines guide tells you to, backed by a Mutex[1]. The coroutineBinding isn't even the main selling point of the library, you can use it without using this feature entirely.

Please could you elaborate on what "looking thread safe" means to you? The only portion of the library that supports concurrency *is* thread safe - the unit tests[2] prove it and the use of concurrency primitives such as Kotlin's Mutex[3] are indicative of this.

I truly have no idea how you've judged the entirely of the library on whether it's "thread safe" when there is a single function (in an extension library, not the core one) that's related to concurrency and it is very clearly using concurrency primitives as intended.

With regards to "being cautious using it", you don't need to be. The maven central statistics suggest its being downloaded 300,000 times per month. If there was something wrong with it, it's likely somebody would have raised this already given how frequently the project has been adopted over the last seven years.

[1] https://github.com/michaelbull/kotlin-result/blob/master/kot...

[2] https://github.com/michaelbull/kotlin-result/blob/master/kot...

[3] https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-corout...

Re:JEP draft: Exception handling in switch by michaelbull on Saturday April 20, 2024 @03:42PM (#40100365)
> Unless JetBrains rolls out language support for something like Rust’s Result, exceptions are superior and Kotlin community would better off embracing them instead of trying to be different for the sake of being different.

If this was true, why do Jetbrains themselves keep reinventing their own per-domain Result classes for their new code? For example, in their coroutines library they invented another Result type specifically for Channels[1] and isn't interoperable at all with their other Result type[2] that was also originally written to facilitate some of the coroutines code.

If Jetbrains' own internal library authors keep reaching for a Result type then I think we're better off following suit, because if they thought exceptions were superior in this example, they would have used them.

[1] https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-corout...

[2] https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/