1. 7

  2. 3

    I find it interesting that a lot of reasons have to do with type-level ambiguities. I know that when I first looked at Throwables.propagate, I also assumed it returned a (possibly) wrapped version of the same exception, and actually would often have blocks of the form

    try {
        // ...
    } catch (IOException e) {
        throw Throwables.propagate(e);

    In fact, this was standard style on some of the projects at my job this summer.

    The more I’ve been playing with Rust, the more I’m starting to think that they get it the most correct of any language I’ve worked with. I see Result<E, T> as the more or less the typed version of C’s -1 return values, with the added bonus of being pleasantly chainable in a way that propagates the error up without having to do so explicitly (i.e. map).

    1. 8

      Welcome to where the ML world has been for 40 years.

      Checked exceptions made sense, sort of, when Java didn’t have generics. Errors as values are cumbersome when your languages is bad at dealing with values, and the instinct to remove boilerplate and nudge people towards effective approaches is a good one. But in Java they’ve ended up as a second parallel type system, and worse, they’ve broken the ability to express the result of function evaluation as a value, even in “expected/normal” code paths (because any code path where it makes sense to use a checked rather than unchecked exception is probably in some sense expected).