google / guava

Google core libraries for Java
Apache License 2.0
50.1k stars 10.87k forks source link

Checked exception bridge for lambdas #1670

Open gissuebot opened 9 years ago

gissuebot commented 9 years ago

Original issue created by cow...@bbs.darktech.org on 2014-02-15 at 09:26 PM


Following-up on http://java8blog.com/post/37385501926/fixing-checked-exceptions-in-java-8 we need the ability to wrap a checked exception thrown by the lambda, then unwrapping the same type on the outside.

The blog I linked to only covers half of the equation (wrapping checked exceptions) but fails to unwrap them back on the outside (which we should do).

gissuebot commented 9 years ago

Original comment posted by cpovirk@google.com on 2014-02-18 at 03:39 PM


Can you give some more detail about what the new methods would look like? Would we be adding mapWithException, filterWithException, and so on for each lambda-accepting method, or is there a generic solution?


Labels: Type-Addition

gissuebot commented 9 years ago

Original comment posted by cow...@bbs.darktech.org on 2014-02-18 at 06:39 PM


Good point. I initially thought there would be a generic solution, but you made me realize that between the time we catch an exception, and the time we throw it, we must invoke some variable method.

Is there a way for us to leverage method handles somehow? In an ideal world, a user would invoke this:

  Throwables.propagate(Files::walk, myLambda, IOException.class)

and under the hood, this would translate to:

try {   Files.walk(() ->   {     try     {       myLambda();     }     catch (IOException e)     {       throw new CheckedExceptionWrapper(e);     }   ); } catch (CheckedExceptionWrapper e) {   throw (IOException) (e.getCause(); }

I'm not familiar enough with method handles. Do you think this would be possible?

gissuebot commented 9 years ago

Original comment posted by lowasser@google.com on 2014-02-18 at 06:42 PM


I'm not sure what you mean about method handles. There are conceivable types for which this would work, it just looks like it'd require a "block with checked exception" interface...?

gissuebot commented 9 years ago

Original comment posted by cow...@bbs.darktech.org on 2014-02-18 at 06:48 PM


Re: method handles, I'm saying that for this to be generic you will need to construct method invocations and catch/throw using dynamically-constructed types.

Notice how above I wrote that the user passes in Files::walk and you translate this into an actual method invocation under the hood. I'm wondering if you could do the same for throwing/catching IOException.

What did you have in mind (provide pseudocode) for "block with checked exception"?

gissuebot commented 9 years ago

Original comment posted by lowasser@google.com on 2014-02-18 at 06:54 PM


You might be able to reuse interfaces more effectively here, somewhere...

interface ThrowingRunnable<X extends Exception> {   public void run() throws X; }

<X extends Exception, Y extends Exception>    void Throwables.propagate(       Consumer<Runnable> consumer,       ThrowingRunnable<X> operation,       Class<X> clazz) {    try {      consumer.accept(() -> {        try {          operation.run();        } catch (Exception e) {          if (clazz.isInstance(e)) {            throw new CheckedExceptionWrapper(e);          }        }      });    } catch (CheckedExceptionWrapper e) {      throw clazz.cast(e.getCause());    } }