Why this Java lambda expression parameter has an error? - java

This is an aritmetic expression evaluator that uses the interpreter GOF pattern, BinaryOp is a non terminal expression.
public class BinaryOP<T> implements Expression<T> {
private Expression<T> e1;
private Expression<T> e2;
private BiFunction<Expression<T>, Expression<T>, T> f;
public BinaryOp(Expression<T> e1, Expression<T> e2,
BiFunction<Expression<T>, Expression<T>, T> f){
this.e1 = e1; this.e2 = e2; this.f = f;
}
#Override
public <T> T interpret(IContext context){
return (T)f.apply(e1, e2);
}
}
And variable is the terminal expression.
public class Variable<T> implements Expression<T> {
private T v;
public Variable(T v){
this.v = v;
}
#Override
public <T> T interpret(IContext context){
return (T)context.recognize(v);
}
}
When defining the BiFunction sum I get an error when using the lambda, an error on its parameters, if a and b are of type expression and the result returns an integer ¿Why is this error?.
public class AritmeticInterpreter
{
public static void main(String[] args) {
IContext<Integer> ctxArimetic = value -> value;
BiFunction<Expression<Integer>, Expression<Integer>, Integer> sum
//Error = incompatible types: incompatible parameter types in lambda expression
= (a, b, result) -> {
return (Integer)a.interpret(ctxArimetic) + (Integer)b.interpret(ctxArimetic);
};
}
}
What is causing this error, has to be the return type another expression?
if I change the interpret method return type to expression, I wouldn't be able to sum two expressions a and b like this:
(a, b) -> a + b
because they are not Integers.
and well, this no part of the title but, ¿can I get rid of casting interpret on method? I know that java compiler erases the generic type but, ¿is there a way?
Update:
Here is the Expression interface.
public interface Expression<T> {
public <T> T interpret(IContext context);
}

Acording to JB Nizet comment and this example I found that I just have to use a and b as arguments in the lambda.
Here is the correct code.
public static void main(String[] args) {
IContext<Integer> ctxArimetic = value -> value;
BiFunction<Expression<Integer>, Expression<Integer>, Integer> sum
= (a, b) -> {
return a.interpret(ctxArimetic) + b.interpret(ctxArimetic);
};
}
and for the last question.
on BinaryOP class i make this change:
#Override
public T interpret(IContext<T> context){
return f.apply(e1, e2);
}
and on the Expression Interface:
public interface Expression<T> {
public T interpret(IContext<T> context);
}
This error was because I parametrized the interpret method, and this allows the method to return any object. I remember that the compiler output the error "T#2 is different from type T#1" T#2 was the generic parameter <T> on interpret method and T#1 was the generic type on the class BinaryOp<T>.
I didn't Know how to use lambdas and generics correctly.
Update: Fix some errors, I changed
public T interpret(IContext context);
To
public T interpret(IContext<T> context);

Related

Implementing map function

I am creating a 'SpecialList' and am require to implement the map function. The list should be lazy, and will only produce values when evaluated.
toString() returns "?" if the value is not yet available; returns the string representation of the value otherwise.
get() called when the contents is needed. If the value is already available, return that value; otherwise, compute the value and return it. The computation should only be done once for the same value.
Here's what I have:
public <U> SpecialList<U> map(Function<T, U> mapper) {
if (!this.isAvailable) {
return new SpecialList<U>(this.supplier);
}
return new SpecialList<U>(mapper, value);
}
// private constructor
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
this.isAvailable = false;
}
However, it is telling me that there's no valid constuctor because T cannot be converted to U.
SpecialList.java:65: error: no suitable constructor found for SpecialList(SpecialList<T>.CachedSupplier<T>)
return new SpecialList<U>(this.supplier);
^
constructor SpecialList.SpecialList(U) is not applicable
(argument mismatch; SpecialList<T>.CachedSupplier<T> cannot be converted to U)
constructor SpecialList.SpecialList(Supplier<U>) is not applicable
(argument mismatch; SpecialList<T>.CachedSupplier<T> cannot be converted to Supplier<U>)
Doesn't the 'U' become a T when returned?
How do I go about solving this? I am still a little unclear about the method level generic types. But I was told that I need to add the < U > for my map method.
Below is my code in full:
class SpecialList<T> {
class CachedSupplier<T> {
private Supplier<? extends T> supplier;
private T value;
boolean isAvailable;
public CachedSupplier(Supplier<? extends T> supplier) {
this.supplier = supplier;
}
public T get() {
if (!isAvailable) {
value = supplier.get();
isAvailable = true;
}
return value;
}
}
private CachedSupplier<T> supplier;
private T value;
boolean isAvailable;
private SpecialList(T value) {
this.value = value;
this.isAvailable = true;
}
private SpecialList(Supplier<T> s) {
this.supplier = new CachedSupplier<T>(s);
this.isAvailable = false;
}
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
this.isAvailable = false;
}
private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
this.isAvailable = false;
}
public static <T> SpecialList<T> of(T value) {
return new SpecialList<>(value);
}
public static <T> SpecialList<T> of(Supplier<T> supplier) {
return new SpecialList<>(supplier);
}
public <R> SpecialList<R> map(Function<? super T,? extends R> mapper) {
if (!this.isAvailable) {
return new SpecialList<>(this.supplier);
}
return new SpecialList<R>(mapper, value);
}
public T get() {
if(this.isAvailable) {
return this.value;
} else {
this.value = this.supplier.get();
this.isAvailable = true;
return this.value;
}
}
}
I am still a little confused with Generic Types etc. so please let me know if there's anything odd/I can improve!
Thanks
According to the code you posted, there is a compile-time error in one of the constructors for class SpecialList...
private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
this.isAvailable = false;
}
Firstly, in the code you posted, there is no constructor in inner class CachedSupplier that takes a Function parameter, so you need to add one with this signature:
public <R> CachedSupplier(Function<T, R> mapper)
And the second problem with the SpecialList constructor is the lambda expression. Abstract method apply in interface Function has a parameter, which your lambda expression is missing. So the constructor code should be:
private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>((v) -> mapper.apply(v));
this.isAvailable = false;
}
The problem is your map function is changing the SpecialList type parameter from T to R. But in the fragment highlited by compiler you return still SpecialList.
Things you can do:
If you are not planning to change the type of elements with your map() function, get rid of R, and replace Function<? super T,? extends R> mapper with Function<? super T,? extends T> mapper. However, this way the mapper would be totaly omited, which might not be the desired behaviuor.
Otherwise, you should pass into your SpecialList constructor a combination of the original supplier and new mapper like so:
return new SpecialList<R>(() -> {
T originalValue = this.supplier.get();
return mapper.apply(originalValue);
};
I think you're doing an overkill by checking isAvailable in both, the SpecialList and the CachedSupplier. It seems enough to me to do so in the CachedSupplier and reduce the members of SpecialList to just the supplier (which is, when the value is available, simply a value-getter without additional costly evaluations). And in the constructors you make sure that the supplier is a cached one, when needed (i.e. when you don't have the value yet).
So here's my suggestion. Further comments are directly in the source code (which compiles now without errors or warnings):
class SpecialList<T> {
static class CachedSupplier<R> implements Supplier<R> {
/* R is a priori an idependent parameter. If you call it T again, then you get a warning
* that the original T is hidden within the new nested class (though it wouldn't really matter here),
* as one doesn't need to refer to it. I made it static, as you don't need an instance to define it. */
private Supplier<? extends R> supplier;
private R value;
boolean isAvailable;
public CachedSupplier(Supplier<? extends R> supplier) {
this.supplier = supplier;
this.isAvailable = false;
}
#Override
public R get() {
if (!isAvailable) {
value = supplier.get();
isAvailable = true;
}
return value;
}
}
private Supplier<T> supplier;
private SpecialList(T value) {
/* in this case no lazy evaluation and no caching needed */
this.supplier = () -> value;
}
private SpecialList(Supplier<T> s) {
this.supplier = new CachedSupplier<T>(s);
}
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
}
private <R> SpecialList(Function<R, T> mapper, R v) {
/* This constructor is not needed anymore in my suggested code.
* I left it simply, in order to show how to fix the type errors related to it.
* if I understood correctly the intentions of this constructor,
* R and T have to be swapped w.r.t the original post.
* This is a constructor that uses an R-value and a mapper R->T to create a SpecialList<T> */
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
}
public static <T> SpecialList<T> of(T value) {
return new SpecialList<>(value);
}
public static <T> SpecialList<T> of(Supplier<T> supplier) {
return new SpecialList<>(supplier);
}
public <R> SpecialList<R> map(Function<T, R> mapper) {
/* mapper is here different (opposite direction) than in the last of the constructors.
* Here we have an existing SpecialList containing a value of Type T which will be turned into a
* SpecialList containing a value of type R by applying a mapper T->R after getting the value from
* the original SpecialList */
return new SpecialList<R>(() -> mapper.apply(get()));
}
public T get() {
return this.supplier.get();
}
}
This solution doesn't yet take care of the toString() implementation. When you want to implement also the latter, it might be more natural to make SpecialList a subclass of CachedSupplier (with the additional map- and toString- methods and direct access to isAvailable)

Returning from a Comparable returning generic java.util.function.Function

I have a method which returns a java.util.Function<A, T> where T is generic type. I need T to be an instance of Comparable<T>. Trying to return a method reference in getFunction() I get the error:
Error:(9, 16) java: incompatible types: bad return type in method reference
java.lang.Integer cannot be converted to T
Here is an MCVE:
import java.util.function.Function;
class Main {
public static void main(String[] args) {
System.out.println(getFunction(true).apply(new A(5)));
}
static <T extends Comparable<T>> Function<A, T> getFunction(boolean b) {
if (b) return A::getX;
else return A::getRandomString;
}
}
class A {
private Integer x;
A(int x) {
this.x = x;
}
Integer getX() {
return x;
}
String getRandomString() {
return "Hello Stack Overflow";
}
}
I've tried using the wildcard return type Function<A, ?> but then I cannot call compareTo().
Is there any way to return a Comparable from such a method with type safety?

How to use Java generics method?

I am moving from C++ to Java. Now I am trying a generics method. But the compiler always complains below error
The method getValue() is undefined for the type T HelloTemplate.java /helloTemplate/src/helloTemplate
The error was pointing to t.getValue() line
As I understand, T is class MyValue, which has the method getValue
What is wrong? How Can I fixed this. I am using Java1.8
public class MyValue {
public int getValue() {
return 0;
}
}
public class HelloTemplate {
static <T> int getValue(T t) {
return t.getValue();
}
public static void main(String[] args) {
MyValue mv = new MyValue();
System.out.println(getValue(mv));
}
}
The compiler doesn't know that you are going to pass to getValue() an instance of a class that has a getValue() method, which is why t.getValue() doesn't pass compilation.
It will only know about it if you add a type bound to the generic type parameter T:
static <T extends MyValue> int getValue(T t) {
return t.getValue();
}
Of course, in such a simple example you can simply remove the generic type parameter and write:
static int getValue(MyValue t) {
return t.getValue();
}
Just you need casting before calling the method. return ((MyValue) t).getValue();
, so that compiler can know that it's calling the MyValue's method.
static <T> int getValue(T t) {
return ((MyValue) t).getValue();
}
in case of multiple classes, you can check for instances using instanceofoperator, and the call the method.. like below
static <T> int getValue(T t) {
//check for instances
if (t instanceof MyValue) {
return ((MyValue) t).getValue();
}
//check for your other instance
return 0; // whatever for your else case.

Generic Functional Interface that accepts and returns same type

I'm looking for a functional interface that satisfies the following two requirements:
Should accept and return the same type
The type should be inferred while calling the method on the FunctionalInterface
If the requirement had just been the first, I can create a simple FunctionalInterface as follows:
#FunctionalInterface
public interface MonoFunction<T> {
T apply (T arg);
}
But, this would require the type to be specified while using the interface. But, I want the type to be inferred. Something like the below pseudo-code:
class A {
int a;
}
class B {
int b;
}
public static void main (String[] args) {
A a;
B b;
MonoFunction foo = (obj) -> {
system.out.println (obj)
return obj;
};
a = foo.apply (new A());
b = foo.apply (new B());
}
How do I achieve something like this?
You could use the UnaryOperator<T> but you have to define beforehand what type you're expecting.
UnaryOperator<A> foo = a -> {
system.out.println(a);
return a;
};
Otherwise, just cast your result into the variable type :
a = (A) foo.apply (new A());
b = (B) foo.apply (new B());
Use a generic factory method returning the function:
static <T> UnaryOperator<T> getFooFunction() {
return obj -> {
System.out.println(obj);
return obj;
};
}
public static void main (String[] args) {
A a;
B b;
UnaryOperator<A> fooA = getFooFunction();
a = fooA.apply(new A());
UnaryOperator<B> fooB = getFooFunction();
b = fooB.apply(new B());
System.out.println(fooA==(Object)fooB);
}
Note that getFooFunction() does not only return the same function semantically, given the current implementation (HotSpot/OpenJDK), it will even be the same object, as you can test easily via fooA==(Object)fooB, so there is no reason to sacrifice the Generic’s type safety.
It’s the same thing that happens when you use UnaryOperator.identity().
The other answers already discuss how to use UnaryOperator<T>. While that approach provides the type safety of Java generics, you still have to specify the type upon creating the UnaryOperator. While I would recommend the UnaryOperator approach in most situations, you specifically asked (in the comments) how one might avoid specifying the type <T>, even if you had to give up type safety.
You can make a MonoFunction implementation as follows (unsafe and usually not recommended):
public class MonoFunction {
private UnaryOperator<Object> func;
#SuppressWarnings("unchecked")
public <T> MonoFunction(UnaryOperator<T> func) {
this.func = (UnaryOperator<Object>) func;
}
#SuppressWarnings("unchecked")
public <T> T apply(T obj) {
return (T) func.apply(obj);
}
}
Note that this is not a #FunctionalInterface, so you'll have to put your lambda expression inside a new MonoFunction(...) call, as follows:
public class MonoFunctionTest {
public static void main(String[] args) {
A a;
B b;
MonoFunction foo = new MonoFunction((obj) -> {
System.out.println(obj);
return obj;
});
a = foo.apply(new A()); // toString in A
b = foo.apply(new B()); // toString in B
MonoFunction bad = new MonoFunction((A obj) -> {
System.out.println(obj);
return obj;
});
a = bad.apply(a); // toString in A
b = bad.apply(b); // ClassCastException: B cannot be cast to A
}
}
class A {
public String toString() { return "toString in A"; }
}
class B {
public String toString() { return "toString in B"; }
}
I stress again that this is unsafe, and it is relatively easy to get a ClassCastException as demonstrated.
This is possible using a generic method within a functional interface:
#FunctionalInterface
interface Identity {
< T > T apply( T input );
}
Unfortunately an interface defined like this cannot be implemented using a lambda function. Instead it must be done the old way using a class, and most concisely with an anonymous class:
Identity id = new Identity() {
public < T > T apply( T anyInput ){
// do something
return anyInput;
}
};
This then works for any input:
class A {
int a = 1;
}
String outputString = id.apply( "one" );
int outputInteger = id.apply( 1 );
A outputClass = id.apply( new A() );

java generic type inference based on generic argument

what I'm trying to do is send a generic method(filter) inside generic object(ItemDelegate) to another generic method(getItem). The problem is that the second method(getItem) can not infer the correct type.
// Generic object
public class ItemDelegate<T> {
public <T> T filter() {
return null;
}
}
// Generic method (receiver):
public static <T> T getItem(ItemDelegate<T> delegate) {
T item = delegate.filter();
//... do something
return item;
}
// Usage in code:
getItem(new ItemDelegate<String>() {
public String filter() {
return "Hi!";
}
}
this code generates a compile error in getItem:
type parameters of T cannot be determined; no unique maximal instance exists for type variable T with upper bounds T,java.lang.Object
Can this even be done in java or is there a better way.
Thanks.
This works for me:
// Generic object
public class ItemDelegate<T> {
public T filter() {
return null;
}
// Generic method (receiver):
public static <R> R getItem(ItemDelegate<R> delegate) {
R item = delegate.filter();
// ... do something
return item;
}
public static void main(String[] args) {
// Usage in code:
getItem(new ItemDelegate<String>() {
#Override
public String filter() {
return "Hi!";
}
});
}
}
It is not clear to me what you want - do you want to make filter generic on a different parameter than that of the generic class ItemDelegate<T>? Then I guess you should use a different parameter name as a minimum:
public class ItemDelegate<T> {
public <U> U filter() {
return null;
}
}
or if you need the same parameter, don't redeclare it:
public class ItemDelegate<T> {
public T filter() {
return null;
}
}
Another problem is, you don't actually override filter in your anonymous class here
getItem(new ItemDelegate<String>() {
public String filter(ResultSet x) throws SQLException {
return "Hi!";
}
}
since this filter has a parameter and throws an exception.
These two issues together mean that the compiler can't infer T for ItemDelegate.filter.

Categories

Resources