8 ms·
Java's checked exceptions fit the 5 criteria: 1. It either `throws` or it doesn't 2. If the function `throws` you have to wrap it in try/catch, or make your f
by nemothekid 5mo ago
Java's checked exceptions fit the 5 criteria:
1. It either `throws` or it doesn't
2. If the function `throws` you have to wrap it in try/catch, or make your function `throws`
3. Your function is `red` if it `throws` the same exception.
4. see (2)
5. See the FileReader class in core.
Now, C++ exceptions might not satisfy all of these, but the problems CheckedExceptions were meant to solve still exist in C++ and as a result some style guides forbid them entirely. Like async, the biggest problem with exceptions were the ergonomics.
- dnautics 5mo agoOk, sorry it's been about 20 years since I last javad IIRC you didn't have to declare exceptions in your function signatures. However, wrapping in try/catch seems to violate #3. Try catch is not a heavy lift of a seam between red and blue To be fair, #3 seems to have shades of grey. In some pls, you can call an async function from a sync one by wrapping it in a whole damn event loop system. Should that count?
- Terr_ 5mo ago> Ok, sorry it's been about 20 years since I last javad and you didn't have to declare exceptions in your function signatures. You're probably remembering RuntimeExceptions, which are a subgroup [0] that are exempt from "checking" by the compiler, which means it does not require method signatures to declare "I might emit this." [0] https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/lang/Exception.html https://docs.oracle.com/en/java/javase/26/docs/api/java.base...
- vips7L 5mo agoYou can declare your runtime exceptions too. The compiler won’t enforce you to catch them though. void fn() throws IllegalStateException
- nemothekid 5mo agoYour question just kicks the can down the road. The problem with the article, to me, is the author doesn't want to accept a certain amount of complexity and has erected arbitrary road blocks. To you, a "whole damn event loop system" is too high a price to pay, but try/catch is not. The complexity of exceptions is invisible to you. However there are certain environments (e.g. FFI) where I dont want "the whole damn exception runtime".
- dnautics 5mo agoi mean no? the coloring problem appears to be solvable in zig. i maintain an FFI binding library for the BEAM vm, where once zig finishes its stackless coroutine support, the same zig function written once should be fully interchangeable between non-async, threaded-async, or async-with-yieldpoints-wrapped-in-the-BEAM's-scheduler.
- melagonster 5mo agoMaybe author do not want to hide the complexity in functions?
- lmm 5mo ago> Try catch is not a heavy lift of a seam between red and blue > To be fair, #3 seems to have shades of grey. In some pls, you can call an async function from a sync one by wrapping it in a whole damn event loop system. Should that count? I think you have to count any extra overhead where you can't just write f(), including try/catch. It's always possible to call whatever kind of function from whatever other kind of function if you put enough effort and hackery in, so if we can't use functions of kind x in functions of kind y as normal "f()" function calls then that has to be what we mean by colouring.
- sheept 5mo ago#3 is not satisfied, as you noted in #2. You can call `throws` methods from non-`throws` methods by wrapping the call in a try catch, and `throws` methods can call non-`throws`. There isn't an exclusivity asymmetry like there is for JavaScript async.
- nemothekid 5mo agoThat only applies to Javascript, which, is mostly only red functions anyways (there are no blocking apis in javascript). Javascript doesn't have the coloring problem in the way Python or Rust has it. In Python, you can wrap the call with asyncio.to_thread, in rust with tokio::spawn_blocking.
- sheept 5mo agoI think you got it backwards: JavaScript has the coloring problem while other languages don't. "Red functions are more painful to call" alludes to async functions. Every await yields back to the event loop, which adds overhead. Making every function red/async adds a performance cost (and makes it harder to reason about race conditions), which is why JavaScript has a mix of blue and red functions. Other languages can escape the "red functions can only be called by red functions" trap, like Python asyncio.run or Tokio block_on. JavaScript has no such alternative, not even in Node. Therefore, Python and Rust don't have function coloring, but JavaScript does.
- vips7L 5mo agoI think the big difference is that in an application that cares about throughput and being non-blocking simply blocking isn’t really possible as it affects the whole performance of the application. Wrapping a checked exception in an unchecked one doesn’t do that.
- Terr_ 5mo ago> Like async, the biggest problem with exceptions were the ergonomics. I know it's not a popular take, but I prefer the idea of Checked Exceptions over unchecked ones [0], and suspect current opinions would be vastly different if Java had shipped with some sweet syntactic sugar for: "If an exception that is of kind A or B or C occurs, automatically throw another checked exception X with the original exception as a cause." > Ex: If I'm writing a tool to try to analyze and recommend music that has to handle multiple different file types, I might catch an MP3 library's Mp3TagCorruptException and wrap it into my own FileFormatException. This would reduce the temptation for developers to ruin the type-safety characteristics by wrapping everything in a RuntimeException just to get the ticket out the door. [0] https://news.ycombinator.com/item?id=42946597 https://news.ycombinator.com/item?id=42946597
- skybrian 5mo agoThe problem with Java's checked exceptions is that it has too many kinds of exceptions to choose from and they're overly specific. Compare with Go, which has a single error interface and had it from the beginning, so it's used everywhere. Returning a new kind of error is always a local change, unless it's a function that didn't previously report errors at all. Type systems permit either standardization or fragmentation and that's an ecosystem issue. Another example is that a language without a strong consensus on which string type to use will result in a fragmented ecosystem when each library goes its own way.
- Terr_ 5mo ago> too many kinds of exceptions to choose from I don't understand, why would you need to pick a checked exception? It's the dual or mirror of feeling paralyzed over a return-type because there are "too many kinds of Object to choose from." If you're writing a CrystalBall class with a gaze_deeply() method, you'll probably return your own VisionResult (extends Object) unless it throws your TooCloudedException (extends Exception). When someone else writes a wrapper or higher-level layer that uses your code, then it'll be up to them to convert or wrap those results and exceptions into something suitable for their level of abstraction. > Returning a new kind of error is always a local change One of my axioms here is that return-values and checked-exceptions are two sides of the same architectural type-system coin. While I'm not familiar with Go, that sounds like something that would be a symptom of bad architecture if it occurred for return values. In other words, suppose all Java methods always returned Object [0]. That would also ensure that a new return type is "always a local change" to the compiler, but I think most developers would be rightly horrified if they came across code that worked that way. [0] Let's ignore Java primitives for now.
- gpderetta 5mo agoExceptions are a very good comparison because they also perform non-local control flow. Checked exceptions are a form of coloring, while unchecked aren't. But Java (which has checked exceptions) has an escape into unchecked land in the form of RuntimeError, most async languages do not, short of spawning a background thread (for sync->async) or force blocking (async->sync). Interestingly, Result<T,E> based error models are semantically (and even syntactically, mostly, except for the call-site annotation) equivalent to checked exceptions. Usually these languages have enough abstraction capabilities (HKT for example) to make coloring not an issue, or, again, an escape into unchecked land (for example panic in rust or Go, although the latter hardly counts as having Result-like error handling).