pivovarit / throwing-function

Checked Exceptions-enabled Java 8+ functional interfaces + adapters
Apache License 2.0
365 stars 60 forks source link

Pass custom exception handlers in unchecked() and lift() #28

Open hanslovsky opened 6 years ago

hanslovsky commented 6 years ago

Both the lift() and uncheck() methods would benefit from adding a signature that passes a custom exception handler, e.g:

   default BiFunction<T1, T2, R> unchecked(Function<Exception, R> handler) {
        return (arg1, arg2) -> {
            try {
                return apply(arg1, arg2);
            } catch (final Exception e) {
                return handler.apply(e);
            }
        };
    }

    default BiFunction<T1, T2, Optional<R>> lift(Function<Exception, Optional<R>> handler) {
        return (arg1, arg2) -> {
            try {
                return Optional.of(apply(arg1, arg2));
            } catch (Exception e) {
                return handler.apply(e);
            }
        };
    }

(code not tested but I hope it conveys the idea) The original signatures could just delegate to these appropriately. I created similar classes/methods for a UI package (it was never good enough for a separate package like yours), and I found it very useful to be able to pass a handler, e.g. for displaying information to the user.

pivovarit commented 6 years ago

Good idea. Targeting 2.0.0 :)

boycott670 commented 5 years ago

But then, how can the user of the API deduce a replacement return value R from the thrown Exception object.

I don't see any type of relation between the exception being thrown and and the new replacement return value to use instead.

In the case of a ThrowingFunction<T, R, E extends Exception>, we can use a BiFunction<T, Exception, R> as a customer exception handler, in this case the user has the T and the Exception thrown to decide of the new R value to return.

We can even help the user by giving him precise context and use a BiFunction<T, E, R> as a custom exception handler, but then we need to do some type of unchecked cast to cast the exception thrown to E before calling the exception handler.

hanslovsky commented 5 years ago

Adding the T to the exception handling is a good idea.

msangel commented 5 years ago

Giving empty exception handler we'll be able to ignore the exception [evil.jpg]. That's what I'm looking for, instead of this:

items.forEach(e -> {
try { e.delete(); } catch (Exception ex) {}
});

But this is also a case for such functionality:

items.stream().map(e -> {
    try {
        e.delete();
        return true;
    } catch (Exception ex) {
        return false;
    }
}).collect(Collectors.toList());