Hacker News new | past | comments | ask | show | jobs | submit login

Only with checked exceptions, which I think most of java has made an anti-pattern now?



No, it's got nothing to do with checked exceptions. It's from not wanting all the error-handling noise between the two steps of your happy-path logic.

And at least in extant Java code and many Java programmers I interview, it's not considered an anti-pattern (but I agree it should be).


It's quite trivial to write a generic function that handles a particular exception else returns a default value, which addresses the above scenario.

    final var x = getOrDefault(C::foo, Something.class, quux());
    return x.bar();
And now with pattern matching in Java, it's trivial to write something similar to Rust's/Scala's `Result<T, E>`/`Try<T>` types and be explicit about all exceptions.

I haven't compiled the following, but it's along the lines of:

    final var x = switch (foo()) {
        case Ok(var r) -> r;
        case Error e -> quux();
    }
    return x.bar();


Neither of those is equivalent to what I wrote (in different ways!), and the first one doesn't even work because of type erasure - you can't write generic functions over exception types. You're also focused way too much on the specific lines I wrote and not the general pattern that leads to exception over-handling.

> trivial... trivial

Rethink your use of this word.

Anyway, alternative proposals don't really matter - I could also offer patterns for Go which make accidentally ignoring error values more difficult. We're talking about actually extant code, and nobody writes Java (or Go) like that outside of forum arguments.


> and the first one doesn't even work because of type erasure - you can't write generic functions over exception types.

It sure does work :-)

    @FunctionalInterface
    interface ThrowingSupplier<R, E extends Exception> {
        R get() throws E;
    }

    static <T, E extends Exception> T getOrDefault(ThrowingSupplier<T, E> f, Class<E> exceptionType, T def) throws E {
        try {
            return f.get();
        } catch (Exception e) {
            if (exceptionType.isInstance(e)) {
                return def;
            }
            throw e;
        }
    }

> and nobody writes Java (or Go) like that outside of forum arguments.

https://www.javadoc.io/doc/io.vavr/vavr/0.9.3/io/vavr/contro...

And now that Java has sealed types and pattern matching, it might become more popular. Kotlin already has them (even without the exhaustive pattern matching that Java has): https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/


> It sure does work :-)

That you've marked the function `throws E` is an admission it doesn't really work; that's the one exception type it definitely doesn't throw. (Default handling is also still different than the starting point.)

Please just stop trying to show off how much you know when I'm trying to discuss how programs in general are actually implemented. You're very clever, but part of why you keep getting it slightly wrong is because probably you don't even write error handling like this day to day.


> That you've marked the function `throws E` is an admission it doesn't really work

Correct, I didn't spend a lot of time refining it. I suppose the only way to make it work is to remove `throws E` from the signature and make it `throw new RuntimeException(e)`, and be similar to C#/Kotlin/Scala.

My last JVM job used Scala, and we wrote things that are similar to

    val x = foo() match {
      case Success(res) => res
      case Error(e) => return quux() // Returns from function scope
   }




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: