Does not pertinent to applicability mean not used?
Zhong Yu
zhong.j.yu at gmail.com
Thu May 1 14:46:18 UTC 2014
On Thu, May 1, 2014 at 4:11 AM, Timo Kinnunen <timo.kinnunen at gmail.com> wrote:
> What’s more, not incorporating those constraints doesn’t automatically mean
> type inference will fail and cause a compile error. This kind of code that’s
> currently rejected by Javac can end up compiling and typechecking correctly
> instead:
>
> public static void main(String[] args) {
> System.out.println(test(Stream.of(Stream.of("3"))));
> System.out.println(test2(Stream.of(Stream.of("1")).skip(1)));
> System.out.println(test31(Stream.of(Stream.of("2")).skip(1)));
> }
>
> static Optional<Stream<Object>> test(Stream<Stream<String>> s31) {
> return s31.map(s2 -> s2.map(s1 -> Integer.parseInt(s1))).findAny();
> }
I would not want s32.map() return type to be inferred as
Stream<Stream<Object>>, regardless whether it's doable by the machine.
It is too much work for the programmer to come to the same conclusion;
too much contextual information needs to be considered for the
inference.
The real problem here is that Optional<Stream<Integer>> is-not-a
Optional<Stream<Object>>. If the return type of test() is changed to
Optional<? extends Stream<? extends Object>>, the code compiles. But
yikes! That is unbearable! Java needs to do something about wildcards,
badly.
>
> static Object test2(Stream<Stream<String>> s3) {
> return s3.map(s2 -> s2.map(s1 ->
> Integer.parseInt(s1))).flatMap(Function.identity()).findAny().orElse(Object.class);
> }
Here we need a lower-bounded type parameter
<S super T> S orElese(S other)
this feature becomes more and more needed when we go beyond the
original use cases of generics that mainly focused on Collection APIs.
>
> static Stream<Object> test31(Stream<Stream<String>> s3) {
> return s3.map(s2 -> s2.map(s1 ->
> Integer.parseInt(s1))).findAny().orElse(Stream.of((Object) "gotcha!"));
> }
>
> This doesn’t even seem to be unsound, just less useable, so it could be
> argued that this is really what should be allowed and enforced and what
> Javac should be changed to treat as correct too.
>
>
>
> --
> Have a nice day,
> Timo.
>
> Sent from Windows Mail
>
> From: Rafkind, Jon
> Sent: Thursday, May 1, 2014 01:13
> To: Zhong Yu, Timo Kinnunen
> Cc: lambda-dev at openjdk.java.net
>
> On 04/29/2014 06:45 PM, Zhong Yu wrote:
>> If an argument is not pertinent to applicability, it is ignored during
>> the applicability test. Other than that, I don't see what effect it
>> has.
>>
>> Consider this simple code
>>
>> void test(Stream<String> ss)
>> {
>> ss.map( s->Integer.parseInt(s) );
>> }
>>
>> The implicit lambda expression is not pertinent to applicability; it
>> does not prevent the compiler from inferring that the invocation
>> returns Stream<Integer>
>
> I think this case is different because the lambda is added as an
> additional constraint, as per 18.5.2:
>
> "For all i (1 ≤ i ≤ k), additional constraints may be included,
> according to the form of ei:
> If the expression is a LambdaExpression, the set contains
> ⟨LambdaExpression →throws Fi θ⟩."
>
> FWIW, my compiler also reports an error on this line
>
> Map<String, List<String>> methodReferenceVersionWithError() {
> return s2.flatMap(p -> entryToStream(p).map(p::replaceKey)).collect(c2);
> }
>
> When the type if flatMap() is inferred the constraint 'p ->
> entryToStream ...' is added. Reducing that lambda constraint produces
> the constraint 'map(p::replaceKey) -> Stream<%a1>', where map() is a
> poly invocation. Reducing a poly invocation reduces to the set B3 that
> is described in section 18.5.2 as per 18.2.1:
>
> "If the expression is a class instance creation expression or a method
> invocation, the constraint reduces to the bound set B3 which would be
> used to determine the expression's invocation type when targeting T, as
> defined in 18.5.2 (in the case of a class instance creation, the
> corresponding "method" used for inference is defined in 15.9.3)."
>
> But B3 ignores non-pertinent expressions so p::replaceKey is not used in
> a constraint formula. B3 basically comprises the pertinent expressions
> and the return type.
More information about the lambda-dev
mailing list