GithubHelp home page GithubHelp logo

pivovarit / throwing-function Goto Github PK

View Code? Open in Web Editor NEW
358.0 21.0 60.0 299 KB

Checked Exceptions-enabled Java 8+ functional interfaces + adapters

License: Apache License 2.0

Java 100.00%
java-8 functional-programming exception-handling hacktoberfest

throwing-function's Introduction

Checked-Exceptions-enabled Java 8+ Functional Interfaces

and adapters

Build Status License Maven Central

Rationale

Standard java.util.function Functional Interfaces aren't checked-exception-friendly due to the absence of throws ... clause which results in tedious and verbose necessity of handling them by adding try-catch boilerplate.

Which makes one-liners like this:

path -> new URI(path)

become as verbose as:

path -> {
    try {
        return new URI(path);
    } catch (URISyntaxException e) {
        throw new RuntimeException(e);
    }
}

By applying com.pivovarit.function functional interfaces, it's possible to regain clarity and readability:

ThrowingFunction<String, URI, URISyntaxException> toUri = URI::new;

and use them seamlessly with native java.util.function classes by using custom ThrowingFunction#unchecked adapters:

...stream()
  .map(unchecked(URI::new)) // static import of ThrowingFunction#unchecked
  .forEach(System.out::println);

which avoids ending up with:

 ...stream().map(path -> {
     try {
         return new URI(path);
     } catch (URISyntaxException e) {
         throw new RuntimeException(e);
     }}).forEach(System.out::println);

Basic API

Functional Interfaces

Adapters

  • static Function<T, R> unchecked(ThrowingFunction<> f) {...}

Transforms a ThrowingFunction instance into a standard java.util.function.Function by wrapping checked exceptions in a RuntimeException and rethrowing them.

  • static Function<T, Optional<R>> lifted() {...}

Transforms a ThrowingFunction instance into a regular Function returning result wrapped in an Optional instance.

  • default ThrowingFunction<T, Void, E> asFunction() {...}

Returns Throwing(Predicate|Supplier|Consumer) instance as a new ThrowingFunction instance.

Maven Central

<dependency>
    <groupId>com.pivovarit</groupId>
    <artifactId>throwing-function</artifactId>
    <version>1.5.1</version>
</dependency>
Gradle
compile 'com.pivovarit:throwing-function:1.5.1'

Dependencies

None - the library is implemented using core Java libraries.

Version history

  • Fixed visibility issues with ThrowingIntFunction
  • Introduced proper Semantic Versioning
  • Introduced ThrowingIntFunction
  • Moved interfaces to com.pivovarit.function
  • Removed controversial unwrap() functionality

throwing-function's People

Contributors

albertlr avatar azplanlos avatar boycott670 avatar brunoabdon avatar dependabot-preview[bot] avatar dependabot[bot] avatar hlipinski avatar jcstockdale avatar pivovarit avatar rafalnowak avatar robertcsakany avatar szpak avatar tobiasroland avatar trombka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

throwing-function's Issues

Improvement: Support for common primitive functions (int, long, double)

For better or worse,java.util.function package has specific classes for primitives. I think it would make sense to have "feature parity" with the java provided functions, but wanted to hear if this would be something you're willing to look at a PR for before I spend a bit of time writing it.

So a sort of simple example of what this change would allow:

IntStream.of(1,2,3) 
  .map(unchecked(this::takesIntThrowsChecked)));

DoubleStream.of(1.0, 2.0, 3.0) 
   .filter(unchecked(d -> {
       if (d > 2.0) throw Exception("Oh no!");
       return true;
   }));

LongStream.of(1,2,3)
.mapToObj(unchecked(x -> {
   if (x > 2) throw Exception("Oh no!")
   return "" + x;
}); 

Specifically I'd be looking to implement Throwing versions of:

  • DoubleBinaryOperator
  • DoubleConsumer
  • DoubleFunction
  • DoublePredicate
  • DoubleSupplier
  • DoubleToIntFunction
  • DoubleToLongFunction
  • DoubleUnaryOperator
  • IntBinaryOperator
  • IntConsumer
  • IntFunction
  • IntPredicate
  • IntSupplier
  • IntToDoubleFunction
  • IntToLongFunction
  • IntUnaryOperator
  • LongBinaryOperator
  • LongConsumer
  • LongFunction
  • LongPredicate
  • LongSupplier
  • LongToDoubleFunction
  • LongToIntFunction
  • LongUnaryOperator

I imagined doing something like this for each of the above:

interface ThrowingIntFunction<T extends Integer, R, E extends Exception> extends ThrowingFunction<T, R, E> {

    R apply(T arg) throws E;

    static <T, R> Function<T, Optional<R>> lifted(final ThrowingFunction<T, R, ?> f) {
        return requireNonNull(f).lift();
    }

    static <T, R> Function<T, R> unchecked(final ThrowingFunction<T, R, ?> f) {
        return requireNonNull(f).uncheck();
    }

    static <T1, R> Function<T1, R> sneaky(ThrowingFunction<? super T1, ? extends R, ?> function) {
        requireNonNull(function);
        return t -> {
            try {
                return function.apply(t);
            } catch (final Exception ex) {
                return SneakyThrowUtil.sneakyThrow(ex);
            }
        };
    }
}

Duplicate code removal

Many code structures happen to be quite similar and I am quite sure that some 'common denominator' could be extracted.

Static unchecked() function

It would be nice to have a static function unchecked(), defined for all ThrowingFunction types, that could return functional types from java.util.function. Checked exception would be wrapped in RuntimeException instances.

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

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.

Add Try monad support

I find it would be useful to support wrapping throwing-function's in a Try monad. A Try is similar to an Optional in implementation, but specifically represents the success or failure of an operation. It is useful when the the thrown exception should be preserved in a data structure that can then be consumed in a functional manner. jasongoodwin/better-java-monads is a good existing implementation of a Try in java.

Here is an example of what the implementation would look like for adding Try support to the ThrowingFunction.

static <T, R> Function<T, Try<R>> tried(final ThrowingFunction<T, R, ?> f) {
  return requireNonNull(f).try();
}

default Function<T, Try<R>> try() {
  return t -> {
    try {
      return Try.successful(apply(t));
    } catch (final Exception e) {
      return Try.failure(e);
    }
  }
}

Here is a test example of usage.

@Test
void shouldReturnFailedTry() {
  // given
  ThrowingFunction<Integer, Integer, Exception> f1 = givenThrowingFunction("custom exception message");

  // when
  Try<Integer> result = f1.try().apply(42);

  // then
  assertThat(result.isSuccess()).isFalse();
  assertThatThrownBy(() -> result.get())
    .isInstanceOf(Exception.class)
    .hasMessage("custom exception message");
}

Immediete evaluation of throwing blocks

So I usually find myself within this situation:

selection_019

    public static void main(String[] args) {
        int num = readIntFromFile();
    }

    private static Integer readIntFromFile() throws Exception {
        return 4;
    }

So let's see what we can do with the line:

int num = readIntFromFile();

How can this library help me? Best I've found is:

int num = ThrowingSupplier.unchecked(Helpers::readIntFromFile).get();

Would it make sense to implement a method like uncheckedGet:

int num = ThrowingSupplier.uncheckedGet(() -> readIntFromFile());

or

int num = ThrowingSupplier.uncheckedGet(Helpers::readIntFromFile);

Here's a scratchpad I have experimented with.


So, is a function like uncheckedGet worth having? Regardless I hope this was issue was an interesting read.

Some of the com.tngtech test dependencies look dodgy for testing

I got fed up seeing the slf4j no-logger found message each build of my fork, so added the following to in the pom.xml:

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.30</version>
            <scope>test</scope>
        </dependency>

...and saw this crazy long log message! The stupid code (technical debt?) seem to assume that JDK's still contain a Sun corporation jar file, many years after Oracle took over Java! Even if it works, does it? That log message shouldn't be appearing.

[main] INFO com.tngtech.archunit.core.PluginLoader - Detected Java version 1.8.0_272
[main] WARN com.tngtech.archunit.core.importer.ClassFileImporter - Couldn't derive ClassFileSource from Location{uri=jar:file:/C:/Program%20Files/AdoptOpenJDK/jdk-8.0.272.10-hotspot/jre/lib/sunrsasign.jar!/}
java.lang.RuntimeException: java.io.FileNotFoundException: C:\Program Files\AdoptOpenJDK\jdk-8.0.272.10-hotspot\jre\lib\sunrsasign.jar (The system cannot find the file specified)
	at com.tngtech.archunit.core.importer.ClassFileSource$FromJar.<init>(ClassFileSource.java:105)
	at com.tngtech.archunit.core.importer.ClassFileSource$FromJar.<init>(ClassFileSource.java:93)
	at com.tngtech.archunit.core.importer.Location$JarFileLocation.asClassFileSource(Location.java:276)
	at com.tngtech.archunit.core.importer.ClassFileImporter.tryAdd(ClassFileImporter.java:341)
	at com.tngtech.archunit.core.importer.ClassFileImporter.importLocations(ClassFileImporter.java:334)
	at com.tngtech.archunit.core.importer.ClassFileImporter.importClasspath(ClassFileImporter.java:264)
	at com.pivovarit.function.ArchitectureTest.<clinit>(ArchitectureTest.java:32)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:511)
	at org.junit.jupiter.engine.execution.ConstructorInvocation.proceed(ConstructorInvocation.java:56)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.api.extension.InvocationInterceptor.interceptTestClassConstructor(InvocationInterceptor.java:72)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:77)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestClassConstructor(ClassBasedTestDescriptor.java:333)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateTestClass(ClassBasedTestDescriptor.java:280)
	at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:77)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:262)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$2(ClassBasedTestDescriptor.java:256)
	at java.util.Optional.orElseGet(Optional.java:267)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$3(ClassBasedTestDescriptor.java:255)
	at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:29)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:108)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:107)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:71)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:107)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:107)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:75)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:150)
	at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:124)
	at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
	at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
Caused by: java.io.FileNotFoundException: C:\Program Files\AdoptOpenJDK\jdk-8.0.272.10-hotspot\jre\lib\sunrsasign.jar (The system cannot find the file specified)
	at java.util.zip.ZipFile.open(Native Method)
	at java.util.zip.ZipFile.<init>(ZipFile.java:225)
	at java.util.zip.ZipFile.<init>(ZipFile.java:155)
	at java.util.jar.JarFile.<init>(JarFile.java:166)
	at java.util.jar.JarFile.<init>(JarFile.java:103)
	at sun.net.www.protocol.jar.URLJarFile.<init>(URLJarFile.java:93)
	at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:69)
	at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:94)
	at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:122)
	at sun.net.www.protocol.jar.JarURLConnection.getJarFile(JarURLConnection.java:89)
	at com.tngtech.archunit.core.importer.ClassFileSource$FromJar.<init>(ClassFileSource.java:99)

Missing sneaky static method on ThrowingBinaryOperator

ThrowingBiFunctions method
static <T1, T2, R> BiFunction<T1, T2, R> sneaky(ThrowingBiFunction<? super T1, ? super T2, ? extends R, ?> function)
can't be used directly, it'd cause a casting failure, so has to be copied like this in ThrowingBinaryOperator:

    static <T> BinaryOperator<T> sneaky(ThrowingBinaryOperator<T, ?> function) {
        requireNonNull(function);
        return (t1, t2) -> {
            try {
                return function.apply(t1, t2);
            } catch (final Throwable ex) {
                return SneakyThrowUtil.sneakyThrow(ex);
            }
        };
    }

A trick to throw the origin exception without wrapping it

The origin way to handle exception is wrapping it by WrappedException (subtype of RuntimeException).

@FunctionalInterface
public interface ThrowingFunction<T,R,E extends Throwable> {
    R apply(T arg) throws E;
    default Function<T, R> uncheck() {
        return t -> {
            try {
                return apply(t);
            } catch (final Throwable e) {
                throw new WrappedException(e);
            }
        };
    }
}

Actually, I think it is better to throw the exception without wrapping.

Usually, the compile doesn't allow you to do this. However, here is a trick for the generic exception type.

@FunctionalInterface
public interface ThrowingFunction<T,R,E extends Throwable> extends Function<T, R> {
    R apply(T arg) throws E;
    default Function<T, R> uncheck() {
        // Just ignore the compiler's unsafe warning.
        return ((ThrowingFunction<T, R, RuntimeException)this)::apply;
    }
}

Using this trick can even cast the ThrowingFunction to the j.u.f.Function implicitly.

@FunctionalInterface
public interface ThrowingFunction<T,R,E extends Throwable> extends Function<T, R> {
    default R apply(T arg) {
        // Just ignore the compiler's unsafe warning.
        return ((ThrowingFunction<T, R, RuntimeException>)this).applyE(arg);
    }
    // The SAM method
    R applyE(T arg) throws E;
}

the tests should use ExpectedException instead of @Test(expected=SomeException.class)

As this is a library created explicitly for wrapping checked and unchecked exceptions in lambda expressions, I would say that is pretty important to make sure that the exception that you are wrapping is indeed the exception that was originally created, together with it's message, not just the exception type.

Currently the tests are using @Test(expected = WrappedException.class), which will test only if the exception was tested. It's not able to test also the thrown exception message without writing a try-catch block.

    @Test(expected = WrappedException.class)
    public void shouldWrapInRuntimeExWhenUsingUnchecked() throws Exception {
        // given
        final ThrowingBiFunction<Integer, Integer, Integer, Exception> f1 = (i, j) -> { throw new Exception(); };

        // when
        ThrowingBiFunction.unchecked(f1).apply(42, 42);

        // then RuntimeException is thrown
    }

For this situations JUnit has it's ExpectedException rule, that can be used to just exactly do so:

     @Rule
     public ExpectedException thrown= ExpectedException.none();

    @Test
    public void shouldWrapInWrappedEx() throws Exception {
        final Exception cause = new Exception("some message");
        
        thrown.expect(WrappedException.class);
        thrown.expectMessage("some message");
        thrown.expectCause(is(cause));

        // given
        final ThrowingBiFunction<Integer, Integer, Integer, Exception> f1 = (i, j) -> { throw cause; };

        // when
        f1.unchecked().apply(42, 42);

        // then RuntimeException is thrown
        fail("exception expected");
    }

even more, you can also verify the root cause, or expect based on a matcher.

By changing the tests to use ExpectedException instead of @Test(expected = SomeException.class) the tests should be cleaner and will actually test that we indeed are wrapping the exceptions not just throwing a runtime exception that accidentally or not is called WrappedException, thus testing more than before.

Add a functional for no-args no-return case ?

Thank you for this library (the design/usage is very nice).

Context
There is a missing piece in java functional (java.util.function), the no-args no-return case ; "Runnable" is not really fitting design/naming/usage-wise, so people usually end up implementing their own functional, an "Action" (name in the C# world) or "Command" or whatever for this case, something like:

@FunctionalInterface
public interface Action {
    void execute();
}

Question/Request
The idea here, would be to have the equivalent in your library, a "ThrowingAction", if you think it fits the scope/purpose of your library, of course.

Incorrect handling of InterruptedException

There is missing InterruptedException handing in ThrowingFunction.uncheck().

default Function<T, R> uncheck() {
    return t -> {
        try {
            return apply(t);
        } catch (final Throwable e) {
            throw new WrappedException(e);
        }
    };
}

If e is type of InterruptedException then interruption flag will be lost in this handler. So there should be one more catch clause with specific handling of InterruptedException.

default Function<T, R> uncheck() {
    return t -> {
        try {
            return apply(t);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt()
            throw new WrappedException(e);
        } catch (final Throwable e) {
            throw new WrappedException(e);
        }
    };
}

Or maybe runtime check in existing catch-clause.

See: https://stackoverflow.com/questions/22104097/how-does-thread-interrupt-sets-the-flag

This library seems useless for methods with throws Throwable

To start with, I think that SneakyThrowUtil::sneakyThrows should be changed from:

    static <T extends Exception, R> R sneakyThrow(Exception t) throws T {
        throw (T) t;
    }

to

    static <T extends Exception, R> R sneakyThrow(Throwable t) throws T {
        throw (T) t;
    }

and all the other code should be modified to accept Throwable, not letter extends Exception, because this blocks capture of the unchecked Error sub-class of Throwable, thus making this library unusable for methods which annoyingly have throws Throwable method signatures e.g. java.lang.invoke.MethodHandle::invoke* methods.

Often Errors should not be caught, because they can signal a fatal failure which should be allowed to propagate, just as sneaky throwing methods allow bypassing the mistake of checked Exceptions, which should not be caught yet either.

I've forked this project, and on my local copy it looks like replacing letter extends Exception, with letter extends Throwable, on the functional class type parameters works, assume that this type is actually used e.g. not for ThrowingSupplier *.

  • IntelliJ IDEA seems, mostly, good at spotting redundant/iffy stuff like this.

Designing a more flexible API

In case you have implemented this feature, then you can ignore this issue, because i'm browsing your repository at this span 72f4d43..8151ca6.

For example let's take ThrowingConsumer#andThenConsume method, in place of taking a ThrowingConsumer<? super T, E> as a parameter, why don't you take a ThrowingConsumer<? super T, ? extends E>, because if this throws an exception of type E, it can also handle a ThrowingConsumer that throws an exception of type ? extends E.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.