2

I have my own implementation for a few tuples, here's the gist of the code for pair:

public class Pair<A, B>  extends Tuple implements Serializable{
    ...
    public Pair(A a,B b){
        this.a=a;
        this.b=b;
    }
    ...
    public <T> Pair<T,B> mapA(Function<A,T> fun){
        return new Pair<T,B>(fun.apply(a),b);
    }
    ...
}

For some weird reason the following code does not work and the compiler seems to think that the resulting pair from the first mapping is <Object,String>.

List<Pair<String,String>> pairs = ...;
pairs
.stream()
.map(p->mapA(s->s.trim())
.map(p->mapA(s->s.toUpperCase()) //does not recognize a as a string
...

Could this be also Eclipse acting up? Running Eclipse Luna fwiw which seems to do a shitty job in general in determining generic types from functional interfaces.

EDIT: full example as requested

public class Pair<A, B> implements Serializable{
    public final A a;
    public final B b;

    public Pair(A a,B b) {
        this.a = a;
        this.b = b;
    }

    public <T> Pair<T,B> mapA(Function<A,T> fun){
        return new Pair<T,B>(fun.apply(a),b);
    }

}


List<Pair<String,String>> pairs = new ArrayList<>();
pairs.add(new Pair<String,String>("foo","bar"));
pairs.stream()
.map(p->p.mapA(s->s.trim()))
.map(p->p.mapA(s->s.toUpperCase()))
.collect(Collectors.toList());
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Seppo420
  • 2,041
  • 2
  • 18
  • 37

2 Answers2

4

Type inference for a typed method doesn't work with lambdas.

Also, you have a coding error (you were referencing the mapA() method without an instance).

You can fix the problem by explicitly typing the method:

pairs.stream()
.map(p -> p.mapA(s -> s.trim())) // input type is known here from stream
.map(p -> p.<String>mapA(s -> s.toUpperCase())) // but not here

Although only a style issue, you could rewrite the above using method references:

pairs.stream()
.map(p -> p.mapA(String::trim))
.map(p -> p.<String>mapA(String::toUpperCase))
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Works for the example but for some reason not for my actual use case. Triplet triplets ...; triplets.stream().mapC(MyItem::load).mapC(MyItem::getTitle) ... Complains that getTitle is not defined for object. i->i.getTitle() wont work either. – Seppo420 Jul 03 '15 at 07:42
  • I could obviously do something like mapC(r->MyItem.load(ref).getTitle()), but I'd kinda need to map the triplets to elsewhere anyways. – Seppo420 Jul 03 '15 at 07:43
  • Now the example is not working either anymore... darn eclipse... EDIT: turns out it works when using `p.mapA(String::trim)` but not with `p.mapA(s->s.trim())`... The real life case fails with both tho – Seppo420 Jul 03 '15 at 07:50
  • This one did the trick: `triplets.stream().map(t->t.mapC(MyItem::load).map(t->t.mapC(MyItem::getTitle))`... – Seppo420 Jul 03 '15 at 07:57
0

Updated to Eclipse Mars and the issue is completely gone.

Seppo420
  • 2,041
  • 2
  • 18
  • 37