java lambda returning a lambda -


i trying seems relatively basic thing in new jdk8 land of functional programming can't work. have working code:

import java.util.*; import java.util.concurrent.*; import java.util.stream.*;  public class so1 {    public static void main() {       list<number> l = new arraylist<>(arrays.aslist(1, 2, 3));       list<callable<object>> checks = l.stream().                map(n -> (callable<object>) () -> {                   system.out.println(n);                    return null;                }).                collect(collectors.tolist());    } } 

it takes list of numbers , produces list of functions can print them out. explicit cast callable seems redundant. seems to me , intellij. , both agree should work:

list<callable<object>> checks = l.stream().        map(n -> () -> {           system.out.println(n);            return null;        }).        collect(collectors.tolist()); 

however error:

so1.java:10: error: incompatible types: cannot infer type-variable(s) r       list<callable<object>> checks = l.stream().map(n -> () -> {system.out.println(n); return null;}).collect(collectors.tolist());                                                     ^     (argument mismatch; bad return type in lambda expression       object not functional interface)   r,t type-variables:     r extends object declared in method <r>map(function<? super t,? extends r>)     t extends object declared in interface stream 1 error 

you hit limitation of java 8’s target typing applies receiver of method invocation. while target typing works (most of times) parameter types not work object or expression on invoke method.

here, l.stream(). map(n -> () -> { system.out.println(n); return null; }) receiver of collect(collectors.tolist()) method invocation, target type list<callable<object>> not considered it.

it’s easy prove nested lambda expressions work if target type know, e.g.

static <t> function<t,callable<object>> tocallable() {     return n -> () -> {         system.out.println(n);          return null;     }; } 

works without problems , can use solve original problem as

list<callable<object>> checks = l.stream()     .map(tocallable()).collect(collectors.tolist()); 

you can solve problem introducing helper method changes role of first expression method receiver parameter

// turns stream s receiver parameter static <t, r, a> r collect(stream<t> s, collector<? super t, a, r> collector) {     return s.collect(collector); } 

and rewrite original expression as

list<callable<object>> checks = collect(l.stream().map(     n -> () -> {         system.out.println(n);          return null;     }), collectors.tolist()); 

this not reduce complexity of code can compiled without problems. me, it’s déjà vu. when java 5 , generics came out, programmers had repeat type parameters on new expressions while wrapping expression generic method proved inferring type no problem. took until java 7 before programmers allowed omit these unnecessary repetition of type arguments (using “diamond operator”). have similar situation, wrapping invocation expression method, turning receiver parameter, proves limitation unnecessary. maybe rid of limitation in java 10…


Comments

Popular posts from this blog

c++ - QTextObjectInterface with Qml TextEdit (QQuickTextEdit) -

javascript - angular ng-required radio button not toggling required off in firefox 33, OK in chrome -

xcode - Swift Playground - Files are not readable -