Re: Does not pertinent to applicability mean not used?

Timo Kinnunen timo.kinnunen at gmail.com
Tue Apr 29 22:52:55 UTC 2014


Hi, 


Re: “I would expect the code is valid. We expect that something like this
should work:

    Function<Integer, Function<Integer, Integer>> f = x->y->x+y;

i.e. the target type propagates inwards, y is determined to be Integer.”


As far as I know, and this should be taken with a huge grain of salt, the issue isn’t propagating inwards per se. Indeed, both compilers determine the type of the variable “item” to be String in both versions of the code, otherwise the string concatenation of “item” and “s” would fail first. 


Rather, the issue is what happens after that. Do the constraints from the lambda whose target type is not pertinent to the applicability of calling map() propagate back outwards to the receiver of .collect()? ECJ’s reading of the specification says they do not, Javac’s reading of the specification says they do. Which one is correct?


The same issue can be observed with inexact method references, too, the code example just ends up being longer:


import java.util.List;

import java.util.Map;

import java.util.stream.Collector;

import java.util.stream.Stream;


abstract class Entry2<K, V> implements Map.Entry<K, V> {

abstract <N> Entry2<N, V> replaceKey(N value);

}


abstract class DoesNotPertinentMeanNotUsed2 {


abstract Stream<String> entryToStream(Entry2<List<String>, String> p);


Stream<Entry2<List<String>, String>> s2;


Collector<Entry2<String, String>, ?, Map<String, List<String>>> c2;


Map<String, List<String>> methodReferenceVersionWithError() {

//The method collect(Collector<? super Object,A,R>) in the type Stream<Object> is not applicable

//for the arguments (Collector<Entry2<String,String>,capture#1-of ?,Map<String,List<String>>>)

return s2.flatMap(p -> entryToStream(p).map(p::replaceKey)).collect(c2);

}


Map<String, List<String>> lambdaVersionWithError() {

//The method collect(Collector<? super Object,A,R>) in the type Stream<Object> is not applicable

//for the arguments (Collector<Entry2<String,String>,capture#2-of ?,Map<String,List<String>>>)

return s2.flatMap(p -> entryToStream(p).map(string -> p.replaceKey(string))).collect(c2);

}


Map<String, List<String>> versionWithoutError() {

return s2.flatMap(p -> entryToStream(p).map((String string) -> p.replaceKey(string))).collect(c2);

}

}



Hopefully this shows exactly where the difference is.





-- 
Have a nice day,
Timo.

Sent from Windows Mail





From: Zhong Yu
Sent: ‎Wednesday‎, ‎April‎ ‎30‎, ‎2014 ‎01‎:‎36
To: Timo Kinnunen
Cc: lambda-dev at openjdk.java.net





On Tue, Apr 29, 2014 at 3:47 PM, Timo Kinnunen <timo.kinnunen at gmail.com> wrote:
> Hi,
>
>
> This code shows a difference in type inference between ECJ and Javac:
>
>
> package differences.lost.typing;
>
> import java.util.List;
>
> import java.util.Map;
>
> import java.util.stream.Collector;
>
> import java.util.stream.Stream;
>
>
> class DoesNotPertinentMeanNotUsed {
>
> Stream<Stream<String>> s;
>
> Collector<String, ?, Map<String, List<String>>> c;
>
>
> Map<String, List<String>> versionWithError() {
>
> return s.flatMap(t -> t.map(item -> t + item)).collect(c);
>
> }
>
> Map<String, List<String>> versionWithoutError() {
>
> return s.flatMap(t -> t.map((String item) -> t + item)).collect(c);
>
> }
>
> }
>
>
> Javac compiles both versions without error messages, ECJ infers the return type of the .flatMap() method call in the first version to be something like Stream<?> which results in a compile error in the call to .collect().
>
>
> In the versionWithError, the inner lambda expression’s (item -> t + item) type is inexact which means it’s not pertinent to applicability for the call to .map(). I am told this is means it doesn’t affect the inferred return type of .map() method call, leaving it unknown, thus making this code invalid, correctly.

I would expect the code is valid. We expect that something like this
should work:

    Function<Integer, Function<Integer, Integer>> f = x->y->x+y;

i.e. the target type propagates inwards, y is determined to be Integer.

>
>
> In the versionWithoutError, the inner lambda expression ((String) item -> t + item) can be pertinent to applicability so it’s type constraints are considered, leading eventually to the type Stream<String> coming out at the other end, and the code being valid.
>
>
> Which compiler is correct, and why?
>
>
>
>
>
>
>
>
>
> --
> Have a nice day,
> Timo.
>
> Sent from Windows Mail
>


More information about the lambda-dev mailing list