Functional Interface Inheritance Quirk - java

I have a custom interface I've been using for some time that looks something like this:
public interface Function<T, R> {
R call(T input);
}
I'd like to retrofit this interface with both Java's Function as well as Guava's Function, while keeping it a FunctionalInterface. I thought I had the perfect arrangement:
#FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
Both superinterfaces declare the same apply() method, which has been implemented in my interface, leaving only the abstract call() method. Strangely, it won't compile, telling me
Invalid '#FunctionalInterface' annotation; Function<T,R> is not a functional interface
Stranger still, the following variations compile just fine:
#FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
#FunctionalInterface
public interface Function<T, R> extends
com.google.common.base.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
#FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
#Override
R apply(T input);
}
Is there a reason the first version won't compile?

As stated in the comments, it compiles fine with the oracle compiler.
It is an eclipse bug.
Awaiting for a bug fix, personally i will remove the annotation #FunctionalInterface (your 3rd variation):
public interface Function<T, R>
extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
The major inconvenient of this solution is that the eclipse compiler bug prevent from using the Function as a lambda target type.
If you really want to keep #FunctionalInterface on your Function, a (ugly) workaround might be to introduce an intermediate interface:
public interface AdapterFunction<T, R>
extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
#Override
default R apply(T input) {
return null;
}
}
and let your Function extends this AdapterFunction:
#FunctionalInterface
public interface Function<T, R>
extends
AdapterFunction<T, R> {
R call(T input);
#Override
default R apply(T input) {
return call(input);
}
}
In this case, the Function is a valid target type for eclipse too:
Function<String, Object> function = st -> st.toString();

Related

What's wrong with this Java decorator generic class?

I created a Java class to decorate another interface with generics. However, it always has some compiler errors. This is the tailored sample code that could reproduce the error.
public interface GenericInterface<T> {
<U, V> GenericInterface<V> testFunc(BiFunction<? super T, ? super U, ? extends V> biFunction);
}
class GenericClass<T> implements GenericInterface<T> {
private GenericInterface<T> delegate;
public GenericClass(GenericInterface<T> dele) {
this.delegate = dele;
}
#Override
public <U, V> GenericInterface<V> testFunc(BiFunction<? super T, ? super U, ? extends V> biFunction) {
GenericClass<T> impl = new GenericClass<T>(delegate);
return impl.testFunc((t, u) -> {
// Do something here ...
// ...
// Error for argument u: Required type: capture of ? super U, Provided: Object
return biFunction.apply(t, u);
});
}
}
I tried a whole week and could not figure out what's wrong with it. Actually, I am new to advanced Java generics.
Remember, ? is like a one-use new type variable.
Therefore, the ? super T in your argument's BiFunction generics, does not have to be the same type as the ? super T as required by the testFunc invocation.
This is fixable:
#Override
public <U, V> GenericInterface<V> testFunc(BiFunction<? super T, ? super U, ? extends V> biFunction) {
GenericClass<T> impl = new GenericClass<T>(delegate);
BiFunction<T, U, V> b = (t, u) -> {
// do something
return biFunction.apply(t, u);
};
return impl.testFunc(b);
}

Java: Implement recursive cached from cached Function and cached BiFunction

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);
}
}

Java Function in 1.7 (convert lambda expressions)

I am working on an old java application that uses Java 1.7. I would like to make use of the java.util.function.Function interface. However, this is only supported in Java 1.8+.
So I would like to write my own implementation in Java 1.7.
import java.util.Objects;
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v)); // lambda expression
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t)); // lambda expression
}
static <T> Function<T, T> identity() {
return t -> t; // lambda expression
}
}
The above gives me compile errors on the lambda expressions.
Question
How do I write the above lambda expressions in Java 1.7?
Since you can't actually create an interface with default methods, I think your best chance are static methods.
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);
}
}
But like KarelG mentions in the comments, it's really not advisable to do this; not to mention that this isn't nearly as elegant as in Java 8; after all, functional interfaces are pretty much geared towards lambdas, and if you don't have them, all usage will be as awkward as the implementation above.
You can use IntellijIdea to change it automatically, There is a result of IntellijIdea:
import java.util.Objects;
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return new Function<V, R>() {
#Override
public R apply(V v) {
return Function.this.apply(before.apply(v));
}
}; // lambda expression
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
Function<T, V> tvFunction = new Function<T, V>() {
#Override
public V apply(T t) {
return after.apply(Function.this.apply(t));
}
};
return tvFunction; // lambda expression
}
static <T> Function<T, T> identity() {
return new Function<T, T>() {
#Override
public T apply(T t) {
return t;
}
}; // lambda expression
}
}

#FunctionalInterface that also implements andThen?

I'm trying to create a functional interface that can throw an custom exception, what I've come up with is.
public class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
#FunctionalInterface
public interface ThrowingFunction<T, R> {
R apply(T t) throws MyException;
}
This works great for using the apply function but the problem is I'd also like to use the andThen capabilities of Java's functions. When I try to do something like.
ThrowingFunction<Integer, Integer> times2WithException = (num) -> {
if(num == null) {
throw new MyException("Cannot multiply null by 2");
}
return num * 2;
};
times2WithException.andThen(times2WithException).apply(4);
I get the error
Cannot find symbol: method andThen(ThrowingFunction<Integer, Integer>)
Is there something I should use instead of FunctionalInterface? Or is there another function I need to implement to get it to work with andThen?
Thanks!
Functional interfaces are only allowed to specify one unimplemented function. But you can specify default functions that already have an implementation like this:
#FunctionalInterface
public interface ThrowingFunction<T, R> {
R apply(T t) throws MyException;
default <U> ThrowingFunction<T, U> andThen(ThrowingFunction<R, U> follow) {
Objects.requireNonNull(follow); // Fail fast
return t -> follow.apply(this.apply(t));
}
}
Where are you expecting the andThen method to come from? You haven't defined it anywhere!
#FunctionalInterface
interface ThrowingFunction<T, R> {
R apply(T t) throws MyException;
default <V> ThrowingFunction<T, V> andThen(ThrowingFunction<R, V> after) {
return (T t) -> after.apply(apply(t));
}
}
Here, you can take advantage of default methods in interfaces to create an andThen function.

How can I implement Function and BiFunction at the same time?

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.

Categories