try-with-resource equivalent
Closed this issue · 3 comments
I think this implementation of the Try
idiom is quite handy. However, I somehow miss an equivalent to the try-with-resource
statement. I hacked some code and would think of something similar to this:
import java.util.function.Function;
import com.lambdista.util.Try;
public class TryWithResource {
public static <T extends AutoCloseable,R> Function<T, Try<R>> lift(Function<T, R> consumer) {
return (closeable) -> {
return Try.apply(() -> {
try (T in = closeable) {
return consumer.apply(in);
}
});
};
}
}
Some Unit tests:
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Before;
import org.junit.Test;
public class TryWithResourceTest {
private Closeable closeableMock;
private InputStream inputStreamMock;
@Before
public void setup(){
this.closeableMock = mock(Closeable.class);
this.inputStreamMock = mock(InputStream.class);
}
@Test
public void closeAbleShouldBeClosedAfterConsumption() throws IOException{
verify(closeableMock, never()).close();
final String result = TryWithResource.lift(closeable -> "String").apply(closeableMock).get();
verify(closeableMock).close();
assertThat(result, is(equalTo("String")));
}
@Test
public void inputStreamShouldBeClosedAfterConsumption() throws IOException{
verify(inputStreamMock, never()).close();
final String result = TryWithResource.lift(inputStream -> "String").apply(inputStreamMock).get();
verify(inputStreamMock).close();
assertThat(result, is(equalTo("String")));
}
@Test
public void inputStreamShouldBeClosedAfterException() throws IOException{
verify(inputStreamMock, never()).close();
TryWithResource.lift(inputStream -> {throw new RuntimeException();}).apply(inputStreamMock);
verify(inputStreamMock).close();
}
}
Would you consider to add such functionality?
Hi @gtrefs I'll be more than happy to add such functionality. Open a PR.
However, if you didn't mind, I'd ask you some changes:
- Change the statement lambda into an expression lambda
- Change the name from
lift
tocreate
(or whatever you prefer) because I thinklift
would be more appropriate if it turned a function fromA -> B
to a function fromTry<A> -> Try<B>
(in general fromA -> B
toF[A] -> F[B]
).
The result of applying 1 and 2 would be something like the following:
public class TryWithResource {
public static <T extends AutoCloseable, R> Function<T, Try<R>> create(Function<T, R> consumer) {
return closeable -> Try.apply(() -> {
try (T in = closeable) {
return consumer.apply(in);
}
});
}
}
Would you mind writing, besides the test, a simple usage example under the example
package?
Thank you so much for your contribution.
Regards
Nice :). Sure, I can integrate your comments into the code. I know that in Scala there are companion objects which have an apply
method. Thus, you can use the Types in a more funcrional way. However, in Java there is nothing like this. If you don't mind, I would add the static method to the Try
class directly.
public class Try<T> {
// ...
public static <T extends AutoCloseable, R> Function<T, Try<R>> applyWithResource(Function<T, R> consumer) {
return closeable -> Try.apply(() -> {
try (T in = closeable) {
return consumer.apply(in);
}
});
}
}
Your Opinion?
That's OK for me. Thank you!