Problem
I am writing a Result type in Java, and I have found a need for it to have a method that performs an operation which may fail, and then encapulates the value or exception in a new Result object.
I had hoped this would work:
#FunctionalInterface
public interface ThrowingSupplier<R, E extends Throwable>
{
R get() throws E;
}
public class Result<E extends Throwable, V>
{
...
public static <E extends Throwable, V> Result<E, V> of(ThrowingSupplier<V, E> v)
{
try
{
return value(v.get());
}
catch(E e)
{
return error(e);
}
}
...
}
But Java cannot catch an exception defined by a type parameter.
I have also tried using instanceof, but that also cannot be used for generics. Is there any way I can implement this method?
Definitions
This is my result type before the addition of the of method. It's intended to be similar to both Haskell's Either and rust's Result, while also having a meaningful bind operation:
public class Result<E extends Throwable, V>
{
private Either<E, V> value;
private Result(Either<E, V> value)
{
this.value = value;
}
public <T> T match(Function<? super E, ? extends T> ef, Function<? super V, ? extends T> vf)
{
return value.match(ef, vf);
}
public void match(Consumer<? super E> ef, Consumer<? super V> vf)
{
value.match(ef, vf);
}
/**
* Mirror of haskell's Monadic (>>=)
*/
public <T> Result<E, T> bind(Function<? super V, Result<? extends E, ? extends T>> f)
{
return match(
(E e) -> cast(error(e)),
(V v) -> cast(f.apply(v))
);
}
/**
* Mirror of Haskell's Monadic (>>) or Applicative (*>)
*/
public <T> Result<E, T> then(Supplier<Result<? extends E, ? extends T>> f)
{
return bind((__) -> f.get());
}
/**
* Mirror of haskell's Applicative (<*)
*/
public Result<E, V> peek(Function<? super V, Result<? extends E, ?>> f)
{
return bind(v -> f.apply(v).then(() -> value(v)));
}
public <T> Result<E, T> map(Function<? super V, ? extends T> f)
{
return match(
(E e) -> error(e),
(V v) -> value(f.apply(v))
);
}
public static <E extends Throwable, V> Result<E, V> error(E e)
{
return new Result<>(Either.left(e));
}
public static <E extends Throwable, V> Result<E, V> value(V v)
{
return new Result<>(Either.right(v));
}
/**
* If the result is a value, return it.
* If it is an exception, throw it.
*
* #return the contained value
* #throws E the contained exception
*/
public V get() throws E
{
boolean has = match(
e -> false,
v -> true
);
if (has)
{
return value.fromRight(null);
}
else
{
throw value.fromLeft(null);
}
}
/**
* Upcast the Result's type parameters
*/
private static <E extends Throwable, V> Result<E, V> cast(Result<? extends E, ? extends V> r)
{
return r.match(
(E e) -> error(e),
(V v) -> value(v)
);
}
}
And the Either type, designed to closely mirror Haskell's Either:
/**
* A container for a disjunction of two possible types
* By convention, the Left constructor is used to hold an error value and the Right constructor is used to hold a correct value
* #param <L> The left alternative type
* #param <R> The right alternative type
*/
public abstract class Either<L, R>
{
public abstract <T> T match(Function<? super L, ? extends T> lf, Function<? super R, ? extends T> rf);
public abstract void match(Consumer<? super L> lf, Consumer<? super R> rf);
public <A, B> Either<A, B> bimap(Function<? super L, ? extends A> lf, Function<? super R, ? extends B> rf)
{
return match(
(L l) -> left(lf.apply(l)),
(R r) -> right(rf.apply(r))
);
}
public L fromLeft(L left)
{
return match(
(L l) -> l,
(R r) -> left
);
}
public R fromRight(R right)
{
return match(
(L l) -> right,
(R r) -> r
);
}
public static <L, R> Either<L, R> left(L value)
{
return new Left<>(value);
}
public static <L, R> Either<L, R> right(R value)
{
return new Right<>(value);
}
private static <L, R> Either<L, R> cast(Either<? extends L, ? extends R> either)
{
return either.match(
(L l) -> left(l),
(R r) -> right(r)
);
}
static class Left<L, R> extends Either<L, R>
{
final L value;
Left(L value)
{
this.value = value;
}
#Override
public <T> T match(Function<? super L, ? extends T> lf, Function<? super R, ? extends T> rf)
{
return lf.apply(value);
}
#Override
public void match(Consumer<? super L> lf, Consumer<? super R> rf)
{
lf.accept(value);
}
}
static class Right<L, R> extends Either<L, R>
{
final R value;
Right(R value)
{
this.value = value;
}
#Override
public <T> T match(Function<? super L, ? extends T> lf, Function<? super R, ? extends T> rf)
{
return rf.apply(value);
}
#Override
public void match(Consumer<? super L> lf, Consumer<? super R> rf)
{
rf.accept(value);
}
}
}
Example Usage
The main use of this is to convert exception-throwing operations into monadic ones. This allows for (checked) exception-throwing methods to be used in streams and other functional contexts, and also allows for pattern matching and binding on the return type.
private static void writeFiles(List<String> filenames, String content)
{
filenames.stream()
.map(
(String s) -> Result.of(
() -> new FileWriter(s) //Open file for writing
).peek(
(FileWriter f) -> Result.of(
() -> f.write(content) //Write file contents
)
).peek(
(FileWriter f) -> Result.of(
() -> f.close()) //Close file
)
).forEach(
r -> r.match(
(IOException e) -> System.out.println("exception writing to file: " + e), //Log exception
(FileWriter f) -> System.out.println("successfully written to file '" + f + "'") //Log success
)
);
}
Just use the optimistic assumption that the interface fulfills the contract, as ordinary Java code will always do (enforced by the compiler). If someone bypasses this exception-checking, it’s not your responsibility to fix that:
public static <E extends Exception, V> Result<E, V> of(ThrowingSupplier<V, E> v) {
try {
return value(v.get());
}
catch(RuntimeException|Error x) {
throw x; // unchecked throwables
}
catch(Exception ex) {
#SuppressWarnings("unchecked") E e = (E)ex;
return error(e);
}
}
Note that even the Java programming language agrees that it is okay to proceed with this assumption, e.g.
public static <E extends Exception, V> Result<E, V> of(ThrowingSupplier<V, E> v) throws E {
try {
return value(v.get());
}
catch(RuntimeException|Error x) {
throw x; // unchecked throwables
}
catch(Exception ex) {
throw ex; // can only be E
}
}
is valid Java code, as under normal circumstances, the get method can only throw E or unchecked throwables, so it is valid to rethrow ex here, when throws E has been declared. We only have to circumvent a deficiency of the Java language when we want to construct a Result parameterized with E.
You need access to the class of the exception and then use some generics in the catch block.
One simple way is to pass the Class<E> class to the Result.of method:
public static <E extends Throwable, V> Result<E, V> of(
ThrowingSupplier<V, E> v,
Class<E> errorType) {
try {
return value(v.get());
} catch(Throwable e) {
if (errorType.isInstance(e)) {
return error(errorType.cast(e));
}
throw new RuntimeException(e); // rethrow as runtime?
}
}
Usage:
Result.of(() -> new FileWriter(s), IOException.class)
Class.isInstance is the dynamic equivalent of the instanceof static operator, while Class.cast is the same as statically casting: (E) e, except that we don't get a warning from the compiler.
EDIT: You need to think what to do when the catched Throwable is not of the type of the exception you are expecting. I've wrapped it in a RuntimeException and have rethrown it. This allows to keep using a fluent style for your monad, but is not transparent any more, as now any exception is wrapped in an unchecked exception. Maybe you could add a 3rd argument to Result.of to handle this specific case...
Update: this seems not to work at all. I'm keeping it here for now because I've linked to is elsewhere, and because it uses a method provided in other accepted answers, which I would like to continue to investigate.
Using Federico's answer and the answer linked in the comment, I have deduced a solution with the same method signature as the original problem, and I have created a class which encapsulates this functionality for future use.
The Result implementation:
public class Result<E extends Exception, V>
{
...
public static <E extends Exception, V> Result<E, V> of(ThrowingSupplier<V, E> v)
{
try
{
return value(v.get());
}
catch(Exception e)
{
Class<E> errType = Reflector.getType();
if (errType.isInstance(e))
{
return error(errType.cast(e));
}
else
{
throw (RuntimeException) e;
}
}
}
...
}
And the Reflector:
import java.lang.reflect.ParameterizedType;
/**
* This class only exists to provide a generic superclass to {#link Reflector}
* #param <E> The type for the subclass to inspect
*/
abstract class Reflected<E>
{ }
/**
* This class provides the ability to obtain information about its generic type parameter.
* #param <E> The type to inspect
* #author
*/
#Deprecated
public class Reflector<E> extends Reflected<E>
{
/**
* Returns the class corresponding to the type {#code <E>}.
* #param <E> The type to inspect
* #return The class corresponding to the type {#code <E>}
*/
public static <E> Class<E> getType()
{
return new Reflector<E>().getParameterType();
}
private Reflector() {}
private Class<E> getParameterType()
{
final ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
return (Class<E>) type.getActualTypeArguments()[0];
}
}
Related
TLDR: How to implement this function?
public static <T, R> Function<T, R> cachedRecursive(final BiFunction<T, Function<T,R>, R> bifunc) {
}
I need to somehow extract the second argument from the BiFunction so I can return a proper result for the function.
This project is for learning purposes, although I'm stuck with the last part of my task.
First part of the task is to create a Cache class extended from the LinkedHashMap, and this is my Implementation:
public class Cache<K,V> extends LinkedHashMap<K, V> {
private static int MaxSize;
public Cache (int maxSize) {
super(maxSize,1f,false);
MaxSize = maxSize;
}
public Cache () {
super();
}
public int getMaximalCacheSize () {
return MaxSize;
}
#Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > MaxSize;
}
}
As for the second part, it is to create a class for which the function definitions will be added:
public class FunctionCache {
private static class Pair<T, U> {
private T stored_t;
private U stored_u;
public Pair(T t, U u) {
stored_t = t;
stored_u = u;
}
public boolean equals(Object t) {
if (t == this) {
return true;
}
return t == stored_t;
}
public int hashCode () {
return stored_t.hashCode();
}
public T get_first() {
return stored_t;
}
public U get_second() {
return stored_u;
}
}
private final static int DEFAULT_CACHE_SIZE = 10000;
public static <T, R> Function<T, R> cached(final Function<T, R> func, int maximalCacheSize) {
Cache<T, R> cache = new Cache<T,R>(maximalCacheSize);
return input -> cache.computeIfAbsent(input, func);
}
public static <T, R> Function<T, R> cached(final Function<T, R> func) {
Cache<T, R> cache = new Cache<T,R>(DEFAULT_CACHE_SIZE);
return input -> cache.computeIfAbsent(input, func);
}
public static <T, U, R> BiFunction<T, U, R> cached(BiFunction<T, U, R> bifunc, int maximalCacheSize) {
Cache<T, R> cache = new Cache<T, R>(maximalCacheSize);
return (t, u) -> {
Pair<T,U> pairKey = new Pair<T,U>(t,u);
Function<Pair<T,U>, R> something = input -> {
return bifunc.apply(input.get_first(), input.get_second());
};
if (!cache.containsKey(pairKey.get_first())) {
R result = something.apply(pairKey);
cache.put(pairKey.get_first(), result);
return result;
} else {
return cache.get(pairKey.get_first());
}
};
}
public static <T, U, R> BiFunction<T, U, R> cached(BiFunction<T, U, R> bifunc) {
Cache<T, R> cache = new Cache<T, R>(DEFAULT_CACHE_SIZE);
return (t, u) -> {
Pair<T,U> pairKey = new Pair<T,U>(t,u);
Function<Pair<T,U>, R> something = input -> {
return bifunc.apply(input.get_first(), input.get_second());
};
if (!cache.containsKey(pairKey.get_first())) {
R result = something.apply(pairKey);
cache.put(pairKey.get_first(), result);
return result;
} else {
return cache.get(pairKey.get_first());
}
};
}
public static <T, R> Function<T, R> cachedRecursive(final BiFunction<T, Function<T,R>, R> bifunc) {
}
}
This is my problem:
public static <T, R> Function<T, R> cachedRecursive(final BiFunction<T, Function<T,R>, R> bifunc) {
}
I have absolutely no idea how to implement the cachedRecursive function, the previous functions are working with a simple fibonacci test perfectly, However the goal of this task is to implement the cachedRecursive function that takes a BiFunction with the first argument as the input and the second argument a function. Just to complete the code, this is the main class I used to test:
public class cachedFunction extends FunctionCache {
public static void main(String[] args) {
#SuppressWarnings({ "rawtypes", "unchecked" })
BiFunction<BigInteger, BiFunction, BigInteger> fibHelper = cached((n, f) -> {
if (n.compareTo(BigInteger.TWO) <= 0) return BigInteger.ONE;
return ((BigInteger) (f.apply(n.subtract(BigInteger.ONE), f)))
.add((BigInteger)f.apply(n.subtract(BigInteger.TWO), f));
}, 50000);
Function<BigInteger, BigInteger> fib = cached((n) -> fibHelper.apply(n,fibHelper));
System.out.println(fib.apply(BigInteger.valueOf(1000L)));
}
}
There are many drawbacks and mistakes in your code:
static size variables shared across different cache instances (therefore breaking it);
code duplication;
incorrect equals/hashCode contract implementation;
suppressing what should be fixed rather than suppressed;
the code is overly bloated;
and some minor ones (like _-containing lower-cased names, etc).
If you don't mind, I simplify it:
final class Functions {
private Functions() {
}
// memoize a simple "unknown" function -- simply delegates to a private encapsulated method
static <T, R> Function<T, R> memoize(final Function<? super T, ? extends R> f, final int maxSize) {
return createCacheFunction(f, maxSize);
}
// memoize a recursive function
// note that the bi-function can be converted to an unary function and vice versa
static <T, R> Function<T, R> memoize(final BiFunction<? super T, ? super Function<? super T, ? extends R>, ? extends R> f, final int maxSize) {
final Function<UnaryR<T, Function<T, R>>, R> memoizedF = memoize(unaryR -> f.apply(unaryR.t, unaryR.r), maxSize);
return new Function<T, R>() {
#Override
public R apply(final T t) {
// this is the "magic"
return memoizedF.apply(new UnaryR<>(t, this));
}
};
}
private static <T, R> Function<T, R> createCacheFunction(final Function<? super T, ? extends R> f, final int maxSize) {
final Map<T, R> cache = new LinkedHashMap<T, R>(maxSize, 1F, false) {
#Override
protected boolean removeEldestEntry(final Map.Entry eldest) {
return size() > maxSize;
}
};
return t -> cache.computeIfAbsent(t, f);
}
// these annotations generate proper `equals` and `hashCode`, and a to-string implementation to simplify debugging
#EqualsAndHashCode
#ToString
private static final class UnaryR<T, R> {
#EqualsAndHashCode.Include
private final T t;
#EqualsAndHashCode.Exclude
private final R r;
private UnaryR(final T t, final R r) {
this.t = t;
this.r = r;
}
}
}
And the test that tests both results and the memoization contract ("no recalculation, if memoized"):
public final class FunctionsTest {
#Test
public void testMemoizeRecursive() {
final BiFunction<BigInteger, Function<? super BigInteger, ? extends BigInteger>, BigInteger> fib = (n, f) -> n.compareTo(BigInteger.valueOf(2)) <= 0 ? BigInteger.ONE : f.apply(n.subtract(BigInteger.ONE)).add(f.apply(n.subtract(BigInteger.valueOf(2))));
#SuppressWarnings("unchecked")
final BiFunction<BigInteger, Function<? super BigInteger, ? extends BigInteger>, BigInteger> mockedFib = Mockito.mock(BiFunction.class, AdditionalAnswers.delegatesTo(fib));
final Function<BigInteger, BigInteger> memoizedFib = Functions.memoize(mockedFib, 1000);
final BigInteger memoizedResult = memoizedFib.apply(BigInteger.valueOf(120));
Mockito.verify(mockedFib, Mockito.times(120))
.apply(Matchers.any(), Matchers.any());
Assertions.assertEquals("5358359254990966640871840", memoizedResult.toString());
Assertions.assertEquals(memoizedResult, memoizedFib.apply(BigInteger.valueOf(120)));
Mockito.verifyNoMoreInteractions(mockedFib);
}
}
I am using Java 1.7. (old I know, but I am working on a legacy application with a lot of dependencies).
I would like to implement the java.util.function.Function interface in 1.7.
I have the following so far, but am still getting compile errors:
public interface Function<T, R> {
R apply(T t);
public static <T, V, R> Function<V, R> compose(Function<? super V, ? extends T> before, Function<? super T, ? super R> after) {
return new CombiningFunction<T, V, R>(before, after);
}
public static <T, R, V> Function<T, V> andThen(Function<? super T, ? super R> before, Function<? super R, ? extends V> after) {
return new CombiningFunction<T, V, R>(before, after);
}
static <T> Function<T, T> identity() {
return new Function<T, T> {
T apply(T t) { return t; }
}
}
}
class CombiningFunction<T, V, R> implements Function<T, R> {
Function<T, V> first;
Function<V, R> second;
public R apply(T t) {
V intermediate = first.apply(t);
return second.apply(intermediate);
}
}
I need to add a constructor to CombiningFunction, but I am not sure how to add it, as I have tried the following:
public <V, T, R> CombiningFunction(Function<? super V,? extends T> before, Function<? super T,? super R> after) { }
but I get more compile errors on the types when I access the constructor.
Also, the following has errors:
return new Function<T, T> {
T apply(T t) { return t; }
}
Any help with this Function interface would be appreciated.
Compile Errors:
return new CombiningFunction<T, V, R>(before, after);
Expected 0 arguments but found 2
return new CombiningFunction<T, V, R>(before, after);
Expected 0 arguments but found 2
static <T> Function<T, T> identity() {
return new Function<T, T> {
T apply(T t) { return t; }
}
}
'(' or '[' expected ';' expected Cannot resolve symbol 't' Unexpected
token
I would like to use the Function as follows:
/**
* Creates Jwt token and other util methods.
*/
public class JwtTokenUtil {
private String SECRET_KEY = "secret-876123";
public String extractUserName(String token) {
return extractClaim(token, new Function<Claims, String>() {
#Override
public String apply(Claims claims) {
return claims.getSubject();
}
});
}
public Date extractExpiration(String token) {
return extractClaim(token, new Function<Claims, Date>() {
#Override
public Date apply(Claims claims) {
return claims.getExpiration();
}
});
}
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
/**
* Pass in user details, and get a Jwt
* #param userDetails
* #return
*/
public String generateToken(UserDetails userDetails) {
Map<String,Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String,Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10 hrs
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
}
public Boolean validteToken(String token, UserDetails userDetails) {
final String username = extractUserName(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
If you go to the OpenJDK repo you can find the source of the Function class. I am not up to date with available features and classes in Java 7 but I think this should fix some of your issues with Generics
https://github.com/openjdk/jdk/blob/6bab0f539fba8fb441697846347597b4a0ade428/src/java.base/share/classes/java/util/function/Function.java
I built a simple document store, there are entities that have fields of different types, I have a Float, Int and String type. The entity contains an array list of values, if someone updates the schema of the entity I would like to be able to try to convert the values to the new type.
public interface FieldType<T> {
ArrayList<T> values;
}
public class FloatField implements FieldType<Float> {
}
public class StringField implements FieldType<String> {
}
I have thought about using a abstract class with methods as below
public abstract class Field<T> implements FieldType<T> {
abstract public <T> castFromString(String value);
abstract public <T> castFromFloat(Float value);
abstract public <T> castFromInt(Int value);
}
public class FloatField extends Field<Float> {
#override
public <Float> castFromString(String value){
Float castValue = null;
try {
castValue = Float.parseFloat(value);
} catch(Exception e){
}
return castValue;
}
}
I did not really like this solution as I would have to add a new abstract method each time I added an extra type to the system.
Any ideas how I could implement this better?
Maybe you could use the Function<T, R> interface?
public abstract class Field<T> implements FieldType<T> {
...
public <F> T convert(F value, Function<F, T> converter) {
try {
return converter.apply(value);
} catch(Exception e) {
return null;
}
}
...
}
And then specify the converter using a lambda expression or a method reference:
field.convert("1234", BigDecimal::new); //with a method reference
field.convert("1234", s -> new BigDecimal(s)) //with a lambda
This would replace all of your convertXXX methods by one since the return type is inferred from the passed Function.
EDIT:
If you want automatic converting, you would of course have to hard-code these since you wouldn't want to write conversion methods for all 4240 classes in the Java API. This gets messy, though. Maybe something like this in a static helper class or in FieldType itself?
public class WhereverYouWantThis {
private static HashMap<Class<?>, HashMap<Class<?>, Function<?, ?>>> converters = new HashMap<>();
static {
putConverter(String.class, Float.class, Float::parseFloat);
}
private static <T, R> void putConverter(Class<T> t, Class<R> r, Function<T, R> func) {
HashMap<Class<?>, Function<?, ?>> map = converters.get(t);
if(map == null) converters.put(t, map = new HashMap<>());
map.put(r, func);
}
public static <T, R> Function<T, R> getConverter(Class<T> t, Class<R> r) {
HashMap<Class<?>, Function<?, ?>> map = converters.get(t);
if(map == null) return null;
#SuppressWarnings("unchecked")
Function<T, R> func = (Function<T, R>) map.get(r);
return func;
}
public static <T, R> R convert(T o, Class<R> to) {
#SuppressWarnings("unchecked")
Function<T, R> func = (Function<T, R>) getConverter(o.getClass(), to);
return func == null ? null : func.apply(o);
}
}
I don't think you need generics for this. Instead, just try to create a Float from the input String and return null if there be a problem:
public Float castFromString(String value) {
Float castValue = null;
try {
castValue = Float.parseFloat(value);
} catch(Exception e){
// log here
}
return castValue;
}
The reason I don't think generics are needed is that the types involved in the conversion are named/known in your helper methods.
I created a class GenericFunction that implements Function and BiFunction. But it cannot be compiled.
public class GenericFunction<T, U, R> implements
Function<T, R>, BiFunction<T, U, R> {
#Override
public R apply(T t, U u) {
return null;
}
#Override
public R apply(T t) {
return null;
}
}
The error message is:
src\obscure\test\GenericFunction.java:6: error:
types BiFunction<T,U,R> and Function<T,R> are incompatible;
both define andThen(java.util.function.Function<? super R,? extends V>),
but with unrelated return types
public class GenericFunction<T, U, R> implements
^
where T,U,R are type-variables:
T extends Object declared in class GenericFunction
U extends Object declared in class GenericFunction
R extends Object declared in class GenericFunction
1 error
How can I do that?
I have no idea why you would want something like this, but it seemed like an interesting challenge...
The main problem is that both Function & BiFunction implement a default andThen function, both having the exact same signature, so your class doesn't know which to call. You just have to provide your own implementation, then its not ambiguous anymore. However the implementation is tricky.
The java docs say the method:
Returns a composed function that first applies this function to its input, and then applies the after function to the result.
... so that means returning a new GenericFunction, where both apply methods are now compositions.
I give you this monstrosity:
public class GenericFunction<T, U, R> implements Function<T, R>, BiFunction<T, U, R> {
#Override
public R apply(T t, U u) {
return null;
}
#Override
public R apply(T t) {
return null;
}
#Override
public <V> GenericFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
return new GenericFunctionAndThen<>(after);
}
private class GenericFunctionAndThen<V> extends GenericFunction<T, U, V> {
private final Function<? super R, ? extends V> after;
public GenericFunctionAndThen(Function<? super R, ? extends V> after) {
this.after = after;
}
#Override
public V apply(T t) {
return after.apply(GenericFunction.this.apply(t));
}
#Override
public V apply(T t, U u) {
return after.apply(GenericFunction.this.apply(t, u));
}
}
}
This uses the most obscure feature of Java that I know of... I don't even know the name! ClassName.this is used in a nested class to refer to a method (or field) in the enclosing instance, if the method is shadowed.
Extending from #romacafe's answer, one thing that I don't like about it is that GenericFunctionAndThen extends GenericFunction without reusing any of the behaviour of its super class – which looks to me as a bad smell.
Things will be cleaner if you implemented GenericFunction as an interface instead:
public interface GenericFunction<T, U, R> extends Function<T, R>, BiFunction<T, U, R> {
#Override
default <V> GenericFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
return new GenericFunction<T, U, V>() {
#Override
public V apply(final T t, final U u) {
return after.apply(GenericFunction.this.apply(t, u));
}
#Override
public V apply(final T t) {
return after.apply(GenericFunction.this.apply(t));
}
};
}
}
This way you have a simple implementation of the generic behaviour (the andThen method), and you can implement your specific behaviour (the 2 apply methods) in a specific class without relying on inheritance.
Exceptions, especially checked ones, can severely interrupt the flow of program logic when the FP idiom is used in Java 8. Here is an arbitrary example:
String s1 = "oeu", s2 = "2";
Stream.of(s1, s2).forEach(s ->
System.out.println(Optional.of(s).map(Integer::parseInt).get()));
The above code breaks when there's an exception for an unparseable string. But say I just want to replace that with a default value, much like I can with Optional:
Stream.of(s1, s2).forEach(s ->
System.out.println(Optional.of(s)
.map(Integer::parseInt)
.orElse(-1)));
Of course, this still fails because Optional only handles nulls. I would like something as follows:
Stream.of(s1, s2).forEach(s ->
System.out.println(
Exceptional.of(s)
.map(Integer::parseInt)
.handle(NumberFormatException.class, swallow())
.orElse(-1)));
Note: this is a self-answered question.
Presented below is the full code of the Exceptional class. It has a quite large API which is a pure extension of the Optional API so it can be a drop-in replacement for it in any existing code—except that it isn't a subtype of the final Optional class. The class can be seen as being in the same relationship with the Try monad as Optional is with the Maybe monad: it draws inspiration from it, but is adapted to the Java idiom (such as actually throwing exceptions, even from non-terminal operations).
These are some key guidelines followed by the class:
as opposed to the monadic approach, doesn't ignore Java's exception mechanism;
instead it relieves the impedance mismatch between exceptions and higher-order functions;
exception handling not statically typesafe (due to sneaky throwing), but always safe at runtime (never swallows an exception except on explicit request).
The class tries to cover all the typical ways to handle an exception:
recover with some handling code which provides a substitute value;
flatRecover which, analogous to flatMap, allows to return a new Exceptional instance which will be unwrapped and the state of the current instance suitably updated;
propagate an exception, throwing it from the Exceptional expression and making the propagate call declare this exception type;
propagate it after wrapping into another exception (translate it);
handle it, resulting in an empty Exceptional;
as a special case of handling, swallow it with an empty handler block.
The propagate approach allows one to selectively pick which checked exceptions he wants to expose from his code. Exceptions which remain unhandled at the time a terminal operation is called (like get) will be sneakily thrown without declaration. This is often considered as an advanced and dangerous approach, but is nevertheless often employed as a way to somewhat alleviate the nuisance of checked exceptions in combination with lambda shapes which do not declare them. The Exceptional class hopes to offer a cleaner and more selective alternative to sneaky throw.
/*
* Copyright (c) 2015, Marko Topolnik. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public final class Exceptional<T>
{
private final T value;
private final Throwable exception;
private Exceptional(T value, Throwable exc) {
this.value = value;
this.exception = exc;
}
public static <T> Exceptional<T> empty() {
return new Exceptional<>(null, null);
}
public static <T> Exceptional<T> ofNullable(T value) {
return value != null ? of(value) : empty();
}
public static <T> Exceptional<T> of(T value) {
return new Exceptional<>(Objects.requireNonNull(value), null);
}
public static <T> Exceptional<T> ofNullableException(Throwable exception) {
return exception != null? new Exceptional<>(null, exception) : empty();
}
public static <T> Exceptional<T> ofException(Throwable exception) {
return new Exceptional<>(null, Objects.requireNonNull(exception));
}
public static <T> Exceptional<T> from(TrySupplier<T> supplier) {
try {
return ofNullable(supplier.tryGet());
} catch (Throwable t) {
return new Exceptional<>(null, t);
}
}
public static Exceptional<Void> fromVoid(TryRunnable task) {
try {
task.run();
return new Exceptional<>(null, null);
} catch (Throwable t) {
return new Exceptional<>(null, t);
}
}
public static <E extends Throwable> Consumer<? super E> swallow() {
return e -> {};
}
public T get() {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
throw new NoSuchElementException("No value present");
}
public T orElse(T other) {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
return other;
}
public T orElseGet(Supplier<? extends T> other) {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
return other.get();
}
public Stream<T> stream() {
return value == null ? Stream.empty() : Stream.of(value);
}
public<U> Exceptional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (value == null) return new Exceptional<>(null, exception);
final U u;
try {
u = mapper.apply(value);
} catch (Throwable exc) {
return new Exceptional<>(null, exc);
}
return ofNullable(u);
}
public<U> Exceptional<U> flatMap(Function<? super T, Exceptional<U>> mapper) {
Objects.requireNonNull(mapper);
return value != null ? Objects.requireNonNull(mapper.apply(value)) : empty();
}
public Exceptional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (value == null) return this;
final boolean b;
try {
b = predicate.test(value);
} catch (Throwable t) {
return ofException(t);
}
return b ? this : empty();
}
public <X extends Throwable> Exceptional<T> recover(
Class<? extends X> excType, Function<? super X, T> mapper)
{
Objects.requireNonNull(mapper);
return excType.isInstance(exception) ? ofNullable(mapper.apply(excType.cast(exception))) : this;
}
public <X extends Throwable> Exceptional<T> recover(
Iterable<Class<? extends X>> excTypes, Function<? super X, T> mapper)
{
Objects.requireNonNull(mapper);
for (Class<? extends X> excType : excTypes)
if (excType.isInstance(exception))
return ofNullable(mapper.apply(excType.cast(exception)));
return this;
}
public <X extends Throwable> Exceptional<T> flatRecover(
Class<? extends X> excType, Function<? super X, Exceptional<T>> mapper)
{
Objects.requireNonNull(mapper);
return excType.isInstance(exception) ? Objects.requireNonNull(mapper.apply(excType.cast(exception))) : this;
}
public <X extends Throwable> Exceptional<T> flatRecover(
Iterable<Class<? extends X>> excTypes, Function<? super X, Exceptional<T>> mapper)
{
Objects.requireNonNull(mapper);
for (Class<? extends X> c : excTypes)
if (c.isInstance(exception))
return Objects.requireNonNull(mapper.apply(c.cast(exception)));
return this;
}
public <E extends Throwable> Exceptional<T> propagate(Class<E> excType) throws E {
if (excType.isInstance(exception))
throw excType.cast(exception);
return this;
}
public <E extends Throwable> Exceptional<T> propagate(Iterable<Class<? extends E>> excTypes) throws E {
for (Class<? extends E> excType : excTypes)
if (excType.isInstance(exception))
throw excType.cast(exception);
return this;
}
public <E extends Throwable, F extends Throwable> Exceptional<T> propagate(
Class<E> excType, Function<? super E, ? extends F> translator)
throws F
{
if (excType.isInstance(exception))
throw translator.apply(excType.cast(exception));
return this;
}
public <E extends Throwable, F extends Throwable> Exceptional<T> propagate(
Iterable<Class<E>> excTypes, Function<? super E, ? extends F> translator)
throws F
{
for (Class<? extends E> excType : excTypes)
if (excType.isInstance(exception))
throw translator.apply(excType.cast(exception));
return this;
}
public <E extends Throwable> Exceptional<T> handle(Class<E> excType, Consumer<? super E> action) {
if (excType.isInstance(exception)) {
action.accept(excType.cast(exception));
return empty();
}
return this;
}
public <E extends Throwable> Exceptional<T> handle(Iterable<Class<E>> excTypes, Consumer<? super E> action) {
for (Class<? extends E> excType : excTypes)
if (excType.isInstance(exception)) {
action.accept(excType.cast(exception));
return empty();
}
return this;
}
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
throw exceptionSupplier.get();
}
public boolean isPresent() {
return value != null;
}
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
if (exception != null) sneakyThrow(exception);
}
public boolean isException() {
return exception != null;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
return obj instanceof Exceptional && Objects.equals(value, ((Exceptional)obj).value);
}
#Override
public int hashCode() {
return Objects.hashCode(value);
}
#SuppressWarnings("unchecked")
private static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
}
#FunctionalInterface
public interface TrySupplier<T> {
T tryGet() throws Throwable;
}
#FunctionalInterface
public interface TryRunnable {
void run() throws Throwable;
}
What if every functional interface provided by java.util.function was allowed to throw an exception?
public interface ThrowingSupplier<R, X extends Throwable> {
public R get() throws X;
}
We could use some default methods to provide the behavior you want.
You could fallback to some default value or action
Or you could try to perform another action which may throw an exception
I've written a library which redefines most of the interfaces in java.util.function this way. I even provide a ThrowingStream which let's you use these new interfaces with the same API as a regular Stream.
#FunctionalInterface
public interface ThrowingSupplier<R, X extends Throwable> {
public R get() throws X;
default public Supplier<R> fallbackTo(Supplier<? extends R> supplier) {
ThrowingSupplier<R, Nothing> t = supplier::get;
return orTry(t)::get;
}
default public <Y extends Throwable> ThrowingSupplier<R, Y> orTry(
ThrowingSupplier<? extends R, ? extends Y> supplier) {
Objects.requireNonNull(supplier, "supplier");
return () -> {
try {
return get();
} catch (Throwable x) {
try {
return supplier.get();
} catch (Throwable y) {
y.addSuppressed(x);
throw y;
}
}
};
}
}
(Nothing is a RuntimeException that can never be thrown.)
Your original example would become
ThrowingFunction<String, Integer, NumberFormatException> parse = Integer::parseInt;
Function<String, Optional<Integer>> safeParse = parse.fallbackTo(s -> null)
.andThen(Optional::ofNullable);
Stream.of(s1, s2)
.map(safeParse)
.map(i -> i.orElse(-1))
.forEach(System.out::println);
Here's some discussions I had previously on this topic.
I made an interface Result<T> along the reasonings. A Result<T> is either a success with a value of type T, or a failure with an Exception. It's a subtype of Async<T>, as an immediately completed async action, but that is not important here.
To create a result -
Result.success( value )
Result.failure( exception )
Result.call( callable )
Result can then be transformed in various ways - transform, map, then, peek, catch_, finally_ etc. For example
Async<Integer> rInt = Result.success( s )
.map( Integer::parseInt )
.peek( System.out::println )
.catch_( NumberFormatException.class, ex->42 ) // default
.catch_( Exception.class, ex-> { ex.printStacktrace(); throw ex; } )
.finally_( ()->{...} )
Unfortunately the API is focusing on Async, so some methods return Async. Some of them can be overridden by Result to return Result; but some cannot, e.g. then() (which is flatmap). However, if interested, it's easy to extract a standalone Result API that has nothing to do with Async.
There's a third-party library called better-java-monads. It has the Try monad which provides the necessary functions. It also has TryMapFunction and TrySupplier functional interfaces to use the Try monad with checked exceptions.