Trouble with wildcards

Remi Forax forax at univ-mlv.fr
Mon Dec 16 13:38:22 PST 2013


On 12/16/2013 03:42 PM, Paul Sandoz wrote:
> Hi Remi,
>
> Reducing it down a little:
>
> import java.util.*;
> import java.util.function.*;
>
> class A {
>
>    static class X {};
>    static class Y extends X {};
>
>    public static void main(String[] args) {
>      Predicate<X> px = x -> x instanceof X;
>      Predicate<Y> py = y -> y instanceof Y;
>
>      Predicate<? super Y> psy = px;
>
>      Predicate<? super Y> superyandy = psy.and(py);    // <-- error
>      superyandy.test(new Y());
>    }
> }
>
> $ javac -Xdiags:verbose A.java
> A.java:15: error: method and in interface Predicate<T> cannot be applied to given types;
>    Predicate<? super Y> superyandy = psy.and(py);    // <-- error
>                                         ^
>    required: Predicate<? super CAP#1>
>    found: Predicate<Y>
>    reason: argument mismatch; Predicate<Y> cannot be converted to Predicate<? super CAP#1>
>    where T is a type-variable:
>      T extends Object declared in interface Predicate
>    where CAP#1 is a fresh type-variable:
>      CAP#1 extends Object super: Y from capture of ? super Y
> 1 error
>
>
> It's confusing...
>
> Paul.

indeed :)

Rémi

>
> On Dec 14, 2013, at 7:43 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>
>> Hi all,
>> I've tried to explain in code how a Stream (here a Flow to avoid
>> confusion) can be implemented (just filter/map, only a sequential
>> stream) with consecutive operations, filter.filter or map.map optimized.
>>
>> I end up with the code below which compiles but if instead of
>>    return Flow.this.filter(/*predicate.and(predicate2)*/ t ->
>> predicate.test(t) && predicate2.test(t));
>> I replace it by
>>    return Flow.this.filter(predicate.and(predicate2));
>> the compiler refuses to compile and I don't understand why :(
>>
>> Here predicate is a Predicate<? super T>, so predicate2 should be a
>> Predicate<? super ? super T>,
>> because and() is declared like this: Predicate<T>.and(Predicate<? super T>)
>> predicate2 is a Predicate<? super T> so it should match Predicate<?
>> super ? super T> but
>> it doesn't.
>>
>> Is it a bug in the compiler or in my head ?
>>
>> cheers,
>> Rémi
>>
>> @FunctionalInterface
>> public interface Flow<T> {
>>    public void forEach(Consumer<? super T> consumer);
>>
>>    public default Flow<T> filter(Predicate<? super T> predicate) {
>>      return new Flow<T>() {
>>        @Override
>>        public void forEach(Consumer<? super T> consumer) {
>>          Flow.this.forEach(u -> {
>>            if (predicate.test(u)) {
>>              consumer.accept(u);
>>            }
>>          });
>>        }
>>        @Override
>>        public Flow<T> filter(Predicate<? super T> predicate2) {
>>          return Flow.this.filter(/*predicate.and(predicate2)*/ t ->
>> predicate.test(t) && predicate2.test(t));
>>        }
>>      };
>>    }
>>
>>    public default <R> Flow<R> map(Function<? super T, ? extends R>
>> function) {
>>      return new Flow<R>() {
>>        @Override
>>        public void forEach(Consumer<? super R> consumer) {
>>          Flow.this.forEach(t -> consumer.accept(function.apply(t)));
>>        }
>>        @Override
>>        public <U> Flow<U> map(Function<? super R, ? extends U> function2) {
>>          return Flow.this.map(function.andThen(function2));
>>        }
>>      };
>>    }
>>
>>    public static <T> Flow<T> create(Iterable<? extends T> iterable) {
>>      return iterable::forEach;
>>    }
>>
>>    public static void main(String[] args) {
>>      List<Integer> list = IntStream.range(0,
>> 10).boxed().collect(Collectors.toList());
>>      Flow<Integer> flow = create(list);
>>      flow.filter(x -> x != 5).filter(x -> x !=
>> 2).forEach(System.out::println);
>>      flow.map(x -> x * 2).map(x -> x + 1).forEach(System.out::println);
>>      flow.filter(x -> x != 5).map(x -> x * 2).filter(x -> x != 2).map(x
>> -> x / 2).forEach(System.out::println);
>>    }
>> }
>>
>
>



More information about the lambda-dev mailing list