Something like
@FunctionalInterface
interface Function<T, R, E extends Throwable> {
R apply(T t) throws E;
}That also includes generic catch clauses and inner exception types of classes with type parameters.
During compilation, type parameters are erased. "T" becomes "Object"; "T extends Something" becomes "Something"; assignment becomes type conversion. But at the end it works correctly. If you try to make something that wouldn't survive the type parameter erasure -- such as having two methods with the same name, one of which accepts "List<String>" and another accepts "List<Integer>" as their input -- it will be a compile-time error, because you can't have two methods with the same name and the same parameter "List".
But imagine that you have a type "MyException" extending RuntimeException, and your code has "catch (MyException)". After compilation, this would become "catch (RuntimeException)", which is wrong, because it would also catch other RuntimeExceptions, and it is not supposed to. But if you make this construction a compile-time error, then... the whole thing becomes useless, because what's the point of having an exception type you cannot catch.
Makes HashMap computeIfAbsent much less useful than it should be. It's impossible to use a function in there that throws a checked exception (all I want is for the exception to propagate out of computeIfAbsent for the parent method to deal with).
Best option I've found is to wrap it in an unchecked exception, then unwrap it in the parent method, which is just .... yuck.
public static void main(String[] args) {
try {
sneakyThrow(new IOException("io"));
Test.<IOException>emulateThrows();
} catch (IOException e) {
e.printStackTrace();
}
}
static void sneakyThrow(Throwable e) {
Test.<RuntimeException>sneakyThrow2(e);
}
private static <E extends Throwable> void sneakyThrow2(Throwable e) throws E {
@SuppressWarnings("unchecked") E e1 = (E) e;
throw e1;
}
static <E extends Exception> void emulateThrows() throws E {
}Was there ever a MacBook with USB-B?
java.util.Date is bad, but it's not getting removed. java.net.URLEncoder is bad, but it's not getting removed.
[1]https://www.artima.com/intv/handcuffs.html [2]https://lrytz.github.io/pubsTalks/ the link to his thesis doesn't work anymore. I cherry pick some of it in my talk for a Scala meetup in Utrecht https://www.slideshare.net/yoozd/effect-systems-in-scala-bey...
But my favorite is abusing the language using Lombok SneakyThrows. It just feels dirty using it. In a good way.
Sometimes I wish Java had one too to complement Optional. I wonder what the argument against that is? Too much confusion with the existing Exception system?
Working with result types is really cumbersome in languages that don't have HKT (Rust hacks around it with a special-purpose language feature), and even more so in languages that also don't have pattern-matching. So I'm not sure how much use it would be in practice. But yeah it's the right way to solve the problem.